<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="rss.xsl"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Vishnu P.S. Blog</title>
        <link>https://www.vishnups.com/blog</link>
        <description>Vishnu P.S. Blog</description>
        <lastBuildDate>Sun, 22 Feb 2026 00:00:00 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Why Your LLM Is Slow (And the 5 Papers That Fix It)]]></title>
            <link>https://www.vishnups.com/blog/why-your-llm-is-slow</link>
            <guid>https://www.vishnups.com/blog/why-your-llm-is-slow</guid>
            <pubDate>Sun, 22 Feb 2026 00:00:00 GMT</pubDate>
            <description><![CDATA[Recently came across a post explaining these papers and thought it worth sharing with a quick breakdown.]]></description>
            <content:encoded><![CDATA[<p>Recently came across a post explaining these papers and thought it worth sharing with a quick breakdown.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="tldr">TLDR<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#tldr" class="hash-link" aria-label="Direct link to TLDR" title="Direct link to TLDR" translate="no">​</a></h2>
<table><thead><tr><th>Concept</th><th>Layer</th><th>Key Win</th><th>Remember This</th></tr></thead><tbody><tr><td>FlashAttention</td><td>Compute</td><td>2-6x attention speedup</td><td>Tiling + IO-awareness</td></tr><tr><td>PagedAttention</td><td>Memory</td><td>Less than 4% waste (was 60-80%)</td><td>Virtual memory for KV cache</td></tr><tr><td>Speculative Decoding</td><td>Generation</td><td>2-3.6x faster decoding</td><td>Draft-then-verify</td></tr><tr><td>Heterogeneous Serving</td><td>Infrastructure</td><td>Up to 77% cost savings</td><td>Right GPU for right job</td></tr><tr><td>DistServe</td><td>Architecture</td><td>7.4x more requests</td><td>Split prefill from decoding</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="1-flashattention---compute-optimisation">1. FlashAttention - Compute Optimisation<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#1-flashattention---compute-optimisation" class="hash-link" aria-label="Direct link to 1. FlashAttention - Compute Optimisation" title="Direct link to 1. FlashAttention - Compute Optimisation" translate="no">​</a></h2>
<p><strong>The problem:</strong> Attention is slow not because of maths, but because of memory traffic. GPUs have fast on-chip memory (SRAM, ~19TB/s) and slow main memory (HBM, ~2TB/s). Standard attention keeps shuffling data between them.</p>
<p><strong>How it works:</strong> Instead of computing the full N×N attention matrix at once, FlashAttention tiles it into small blocks that fit in fast SRAM. It uses an "online softmax" trick to get exact results incrementally - no approximation.</p>
<p><strong>Analogy:</strong> Instead of carrying all your groceries inside in one impossible armful, you make smart small trips - but you planned the route so well it's actually faster.</p>
<table><thead><tr><th>Version</th><th>Speedup</th><th>GPU Utilisation</th></tr></thead><tbody><tr><td>v1</td><td>2-3x vs standard</td><td>25-40%</td></tr><tr><td>v2</td><td>2x on top of v1</td><td>50-73%</td></tr></tbody></table>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="2-pagedattention---memory-management">2. PagedAttention - Memory Management<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#2-pagedattention---memory-management" class="hash-link" aria-label="Direct link to 2. PagedAttention - Memory Management" title="Direct link to 2. PagedAttention - Memory Management" translate="no">​</a></h2>
<p><strong>The problem:</strong> Each request stores a KV cache (the model's "memory" of past tokens). Traditional systems pre-allocate memory for the worst case, wasting 60-80% of GPU memory. This limits how many requests you can batch together.</p>
<p><strong>How it works:</strong> Borrows the virtual memory paging concept from operating systems. KV cache is split into fixed-size blocks that can be scattered anywhere in GPU memory. A block table maps logical to physical locations. Memory is allocated on-demand as tokens are generated.</p>
<p><strong>Analogy:</strong> Instead of reserving an entire bookshelf per person (wasteful), you let people's books sit on any available shelf and give them a card catalogue to find them.</p>
<table><thead><tr><th>Metric</th><th>Result</th></tr></thead><tbody><tr><td>Memory waste</td><td>60-80% to less than 4%</td></tr><tr><td>Throughput vs HuggingFace</td><td>24x</td></tr><tr><td>Throughput vs prior SOTA</td><td>2-4x</td></tr></tbody></table>
<p><strong>Why it matters:</strong> Memory efficiency means larger batch sizes, more requests per GPU, and lower cost. This is why vLLM became the industry standard for LLM serving.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="3-speculative-decoding---faster-token-generation">3. Speculative Decoding - Faster Token Generation<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#3-speculative-decoding---faster-token-generation" class="hash-link" aria-label="Direct link to 3. Speculative Decoding - Faster Token Generation" title="Direct link to 3. Speculative Decoding - Faster Token Generation" translate="no">​</a></h2>
<p><strong>The problem:</strong> LLMs generate tokens one at a time, each requiring a full forward pass through billions of parameters. The GPU is massively underutilised - like hiring 1,000 workers to carry one brick at a time.</p>
<p><strong>Two approaches:</strong></p>
<p><strong>Speculative Sampling (DeepMind):</strong> A small fast "draft" model guesses the next k tokens. The big model verifies all k in one forward pass. If the guesses match, you got k tokens for the price of roughly 1. Mathematically guaranteed to produce identical output.</p>
<p><strong>Medusa (Cai et al., Princeton/UIUC):</strong> Instead of a separate model, bolt extra "prediction heads" onto the main model. Each head predicts future tokens in parallel. Simpler deployment (one model), but requires fine-tuning.</p>
<table><thead><tr><th>Approach</th><th>Speedup</th><th>Trade-off</th></tr></thead><tbody><tr><td>Speculative Sampling</td><td>2-2.5x</td><td>Need two models</td></tr><tr><td>Medusa-2</td><td>2.3-3.6x</td><td>Need to fine-tune heads</td></tr></tbody></table>
<p><strong>Analogy:</strong> Instead of asking the CEO to write a memo word by word, have an intern draft 5 sentences, then the CEO reviews them all at once - keeping what's good, rewriting what's not.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="4-heterogeneous-gpu-serving---cost-optimisation">4. Heterogeneous GPU Serving - Cost Optimisation<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#4-heterogeneous-gpu-serving---cost-optimisation" class="hash-link" aria-label="Direct link to 4. Heterogeneous GPU Serving - Cost Optimisation" title="Direct link to 4. Heterogeneous GPU Serving - Cost Optimisation" translate="no">​</a></h2>
<p><strong>The problem:</strong> Companies buy expensive A100s for everything, but not all requests need top-tier hardware. Short chat messages don't need the same GPU as processing 100-page documents.</p>
<p><strong>Two approaches:</strong></p>
<p><strong>Metis (training-focused):</strong> Automatically figures out how to split training across mixed GPU types with smart load balancing. Result: 1-8.4x speedup.</p>
<p><strong>Melange (inference-focused):</strong> Formulates GPU selection as a bin-packing problem - which mix of cheap and expensive GPUs minimises cost while meeting latency targets?</p>
<table><thead><tr><th>Workload</th><th>Cost Savings</th></tr></thead><tbody><tr><td>Short chat</td><td>up to 77%</td></tr><tr><td>Long documents</td><td>33%</td></tr><tr><td>Mixed</td><td>51%</td></tr></tbody></table>
<p><strong>Analogy:</strong> Instead of sending limousines for every taxi ride, dispatch the right vehicle for each trip - sedans for solo riders, vans for groups.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="5-distserve---disaggregated-inference">5. DistServe - Disaggregated Inference<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#5-distserve---disaggregated-inference" class="hash-link" aria-label="Direct link to 5. DistServe - Disaggregated Inference" title="Direct link to 5. DistServe - Disaggregated Inference" translate="no">​</a></h2>
<p><strong>The problem:</strong> LLM inference has two phases with opposite needs:</p>
<ul>
<li class=""><strong>Prefill</strong> (process the prompt): wants massive parallelism, high throughput</li>
<li class=""><strong>Decoding</strong> (generate tokens): wants low latency, small batches</li>
</ul>
<p>Running both on the same GPU is like asking one chef to do both bulk meal prep and delicate plating simultaneously - neither goes well.</p>
<p><strong>How it works:</strong> Physically separate prefill and decoding onto different GPU clusters, each tuned for its workload. After prefill generates the KV cache, it is shipped to the decoding cluster.</p>
<table><thead><tr><th>Metric</th><th>Result</th></tr></thead><tbody><tr><td>Goodput vs vLLM (requests meeting SLO/s)</td><td>7.4x more</td></tr><tr><td>SLO compliance</td><td>Over 90% of requests meet latency targets</td></tr></tbody></table>
<p><strong>Analogy:</strong> A restaurant with a separate prep kitchen (high-volume chopping) and a plating station (precision finishing), connected by a runner.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="references">References<a href="https://www.vishnups.com/blog/why-your-llm-is-slow#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h2>
<ol>
<li class="">Dao et al. (2022) : <a href="https://arxiv.org/abs/2205.14135" target="_blank" rel="noopener noreferrer" class="">FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness</a></li>
<li class="">Dao (2023) : <a href="https://arxiv.org/abs/2307.08691" target="_blank" rel="noopener noreferrer" class="">FlashAttention-2: Faster Attention with Better Parallelism and Work Partitioning</a></li>
<li class="">Kwon et al. (2023) : <a href="https://arxiv.org/abs/2309.06852" target="_blank" rel="noopener noreferrer" class="">Efficient Memory Management for Large Language Model Serving with PagedAttention</a></li>
<li class="">Chen et al. (2023) : <a href="https://arxiv.org/abs/2211.17192" target="_blank" rel="noopener noreferrer" class="">Accelerating Large Language Model Decoding with Speculative Sampling</a></li>
<li class="">Cai et al. (2024) : <a href="https://arxiv.org/abs/2401.02659" target="_blank" rel="noopener noreferrer" class="">Medusa: Simple LLM Inference Acceleration Framework with Multiple Decoding Heads</a></li>
<li class="">Um et al. (2022) : <a href="https://arxiv.org/abs/2208.14226" target="_blank" rel="noopener noreferrer" class="">Metis: Fast Automatic Distributed Training on Heterogeneous GPUs</a></li>
<li class="">Griggs et al. (2024) : <a href="https://arxiv.org/abs/2404.14527" target="_blank" rel="noopener noreferrer" class="">Mélange: Cost Efficient Large Language Model Serving by Exploiting GPU Heterogeneity</a></li>
<li class="">Zhong et al. (2024) : <a href="https://arxiv.org/abs/2401.09670" target="_blank" rel="noopener noreferrer" class="">DistServe: Disaggregating Prefill and Decoding for Goodput-Optimized LLM Serving</a></li>
</ol>]]></content:encoded>
            <category>LLM</category>
            <category>MLOps</category>
        </item>
        <item>
            <title><![CDATA[Building a Production Data Analysis Agent]]></title>
            <link>https://www.vishnups.com/blog/building-a-data-analysis-agent</link>
            <guid>https://www.vishnups.com/blog/building-a-data-analysis-agent</guid>
            <pubDate>Sun, 03 Aug 2025 00:00:00 GMT</pubDate>
            <description><![CDATA[Build a data analysis agent that turns natural language into SQL, runs queries against a database, and returns insights using LangGraph, FastAPI, Redis, LiteLLM, and MCP. Everything runs locally via Docker Compose.]]></description>
            <content:encoded><![CDATA[<p>Build a data analysis agent that turns natural language into SQL, runs queries against a database, and returns insights using LangGraph, FastAPI, Redis, LiteLLM, and MCP. Everything runs locally via Docker Compose.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="tldr">TL;DR<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<ul>
<li class=""><strong>Natural language to SQL</strong> agent backed by a sample e-commerce database</li>
<li class=""><strong>LangGraph</strong> for stateful workflow orchestration with conditional routing</li>
<li class=""><strong>FastAPI</strong> with SSE streaming</li>
<li class=""><strong>Redis</strong> for conversation memory and query caching</li>
<li class=""><strong>LiteLLM</strong> proxy -- swap OpenAI, Anthropic, or Ollama without code changes</li>
<li class=""><strong>MCP</strong> server for external tool access (Claude Desktop, Cursor)</li>
<li class=""><strong>Docker Compose</strong> one-command setup</li>
</ul>
<p><a href="https://github.com/p-s-vishnu/data-agent" target="_blank" rel="noopener noreferrer" class="">Code: Companion code</a></p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="what-is-a-data-analysis-agent">What is a Data Analysis Agent?<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#what-is-a-data-analysis-agent" class="hash-link" aria-label="Direct link to What is a Data Analysis Agent?" title="Direct link to What is a Data Analysis Agent?" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="Autonomy levels" src="https://www.vishnups.com/assets/images/agent_autonomy_levels-8d3d9da62bf1f7741fa7787a60a98743.png" width="1794" height="1150" class="img_dCa6"></p>
<blockquote>
<p>A <strong>workflow</strong> follows predefined paths -- the developer decides the control flow. An <strong>agent</strong> uses an LLM to decide what to do next.</p>
</blockquote>
<p>Our agent sits at <strong>level 2</strong> -- an <strong>Orchestrator-Worker</strong> pattern. A router classifies intent, then delegates to specialised workers (SQL generation, execution, analysis). We define the paths; the LLM picks which one.</p>
<p>Full autonomy (level 3) would be overkill here. We want deterministic tools orchestrated by an LLM that understands context.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="architecture">Architecture<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#architecture" class="hash-link" aria-label="Direct link to Architecture" title="Direct link to Architecture" translate="no">​</a></h2>
<!-- -->
<p><strong>Request flow:</strong></p>
<ol>
<li class="">User sends a question to FastAPI.</li>
<li class="">Conversation history is loaded from Redis.</li>
<li class="">The <strong>router</strong> classifies intent -- data question, follow-up, or general.</li>
<li class="">For data questions: <strong>SQL generator</strong> -&gt; <strong>executor</strong> -&gt; <strong>analyst</strong> -&gt; <strong>responder</strong>.</li>
<li class="">Updated conversation is persisted back to Redis.</li>
</ol>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="why-these-frameworks">Why These Frameworks?<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#why-these-frameworks" class="hash-link" aria-label="Direct link to Why These Frameworks?" title="Direct link to Why These Frameworks?" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="langgraph">LangGraph<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#langgraph" class="hash-link" aria-label="Direct link to LangGraph" title="Direct link to LangGraph" translate="no">​</a></h3>
<blockquote>
<p><a href="https://langchain-ai.github.io/langgraph/" target="_blank" rel="noopener noreferrer" class=""><strong>LangGraph</strong></a> -- stateful, multi-step agent workflows as directed graphs.</p>
</blockquote>
<ul>
<li class=""><strong>Conditional routing</strong> -- the router branches to entirely different paths based on LLM classification. Plain chains cannot do this.</li>
<li class=""><strong>Shared state</strong> -- <code>AgentState</code> carries messages, SQL, results, and analysis across nodes without globals.</li>
<li class=""><strong>Loop-back</strong> -- the analyst can request more data and route back to the SQL generator.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="fastapi">FastAPI<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#fastapi" class="hash-link" aria-label="Direct link to FastAPI" title="Direct link to FastAPI" translate="no">​</a></h3>
<blockquote>
<p><a href="https://fastapi.tiangolo.com/" target="_blank" rel="noopener noreferrer" class=""><strong>FastAPI</strong></a> -- async Python web framework built on Starlette and Pydantic.</p>
</blockquote>
<ul>
<li class="">Native async for non-blocking DB calls and streaming.</li>
<li class="">Auto-generated OpenAPI docs from Pydantic models.</li>
<li class="">SSE streaming via <code>sse-starlette</code> for token-by-token responses.</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="redis">Redis<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#redis" class="hash-link" aria-label="Direct link to Redis" title="Direct link to Redis" translate="no">​</a></h3>
<blockquote>
<p><a href="https://redis.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Redis</strong></a> -- in-memory data store.</p>
</blockquote>
<p>Two use cases:</p>
<ol>
<li class=""><strong>Conversation history</strong> -- keyed by <code>conversation:{id}</code>, 24h TTL.</li>
<li class=""><strong>Query cache</strong> -- keyed by SHA-256 of the SQL, 5min TTL. Avoids re-executing expensive queries during iterative analysis.</li>
</ol>
<p>Sub-millisecond reads. Automatic expiry. No cleanup jobs.</p>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="litellm">LiteLLM<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#litellm" class="hash-link" aria-label="Direct link to LiteLLM" title="Direct link to LiteLLM" translate="no">​</a></h3>
<blockquote>
<p><a href="https://docs.litellm.ai/" target="_blank" rel="noopener noreferrer" class=""><strong>LiteLLM</strong></a> -- proxy server providing a unified OpenAI-compatible API for 100+ LLM providers.</p>
</blockquote>
<p>The agent talks to <code>http://litellm-proxy:4000/v1</code>. Whether that routes to GPT-4.1, Claude Sonnet, or local Ollama is purely config. Also gives you spend tracking, rate limiting, and fallbacks for free.</p>
<div class="theme-admonition theme-admonition-tip admonition_iHmK alert alert--success"><div class="admonitionHeading_BWUg"><span class="admonitionIcon_Q0AD"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_gGp9"><p>For Rust setups, <a href="https://docs.rs/litellm-rs/latest/litellm_rs/index.html" target="_blank" rel="noopener noreferrer" class="">litellm-rs</a> provides a similar interface with lower overhead.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="mcp">MCP<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#mcp" class="hash-link" aria-label="Direct link to MCP" title="Direct link to MCP" translate="no">​</a></h3>
<blockquote>
<p><a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class=""><strong>Model Context Protocol</strong></a> -- standardised protocol for connecting AI models with tools.</p>
</blockquote>
<p>Define tools once via MCP, any compatible client can discover and use them. No per-client integration work.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="implementation">Implementation<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#implementation" class="hash-link" aria-label="Direct link to Implementation" title="Direct link to Implementation" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="docker-compose--litellm">Docker Compose + LiteLLM<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#docker-compose--litellm" class="hash-link" aria-label="Direct link to Docker Compose + LiteLLM" title="Direct link to Docker Compose + LiteLLM" translate="no">​</a></h3>
<p>Four services:</p>
<div class="language-yaml codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">docker-compose.yml</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-yaml codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">services</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">litellm-proxy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ghcr.io/berriai/litellm</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">main</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">latest</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"4000:4000"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./litellm/config.yaml</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/app/config.yaml</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">command</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"--config"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"/app/config.yaml"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">env_file</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> .env</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">healthcheck</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">test</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"CMD"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"curl"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"-f"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"http://localhost:4000/health"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">interval</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 10s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">timeout</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> 5s</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">retries</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">5</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">7</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"6379:6379"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">image</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">16</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">alpine</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">environment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">POSTGRES_DB</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ecommerce</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">POSTGRES_USER</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgres</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">POSTGRES_PASSWORD</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgres</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">volumes</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> ./db/init.sql</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">/docker</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">entrypoint</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">initdb.d/init.sql</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token key atrule" style="color:#00a4db">agent-api</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">build</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">ports</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"8000:8000"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">env_file</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> .env</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">environment</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">LITELLM_BASE_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> http</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//litellm</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">proxy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">4000/v1</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">REDIS_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">6379/0</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">DATABASE_URL</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> postgresql+asyncpg</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">//postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">postgres@postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain">5432/ecommerce</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">depends_on</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">litellm-proxy</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">condition</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> service_healthy</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">redis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">condition</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> service_started</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">postgres</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token key atrule" style="color:#00a4db">condition</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> service_started</span><br></span></code></pre></div></div>
<p>LiteLLM config with multiple providers:</p>
<div class="language-yaml codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">litellm/config.yaml</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-yaml codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token key atrule" style="color:#00a4db">model_list</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">model_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> gpt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">4.1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">litellm_params</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">model</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> openai/gpt</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">4.1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">api_key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> os.environ/OPENAI_API_KEY</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">model_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> claude</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">sonnet</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">litellm_params</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">model</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> anthropic/claude</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">sonnet</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">4</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">5</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">20250929</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">api_key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> os.environ/ANTHROPIC_API_KEY</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain"> </span><span class="token key atrule" style="color:#00a4db">model_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> claude</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">haiku</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token key atrule" style="color:#00a4db">litellm_params</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">model</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> anthropic/claude</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">haiku</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">4</span><span class="token punctuation" style="color:#393A34">-</span><span class="token plain">5</span><span class="token punctuation" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">20251001</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token key atrule" style="color:#00a4db">api_key</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> os.environ/ANTHROPIC_API_KEY</span><br></span></code></pre></div></div>
<p>Dockerfile uses <code>uv</code> for dependency management:</p>
<div class="language-dockerfile codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">Dockerfile</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-dockerfile codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">FROM python:3.12-slim</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">WORKDIR /code</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">COPY pyproject.toml .</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">RUN uv sync --no-dev --no-install-project</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">COPY app/ app/</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">CMD ["uv", "run", "uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="database-schema">Database Schema<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#database-schema" class="hash-link" aria-label="Direct link to Database Schema" title="Direct link to Database Schema" translate="no">​</a></h3>
<p>E-commerce database -- customers, products, and ~200 orders spanning 6 months:</p>
<div class="language-sql codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">db/init.sql</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-sql codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> customers </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id </span><span class="token keyword" style="color:#00009f">SERIAL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    name </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">100</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    email </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">150</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">UNIQUE</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    segment </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">20</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">CHECK</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">segment </span><span class="token operator" style="color:#393A34">IN</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">'enterprise'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'mid-market'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'startup'</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">'consumer'</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    region </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">30</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    created_at </span><span class="token keyword" style="color:#00009f">TIMESTAMP</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">DEFAULT</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">NOW</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> products </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id </span><span class="token keyword" style="color:#00009f">SERIAL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    name </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">150</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    category </span><span class="token keyword" style="color:#00009f">VARCHAR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">50</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    price </span><span class="token keyword" style="color:#00009f">NUMERIC</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">CREATE</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">TABLE</span><span class="token plain"> orders </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    id </span><span class="token keyword" style="color:#00009f">SERIAL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">PRIMARY</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">KEY</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    customer_id </span><span class="token keyword" style="color:#00009f">INTEGER</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> customers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    product_id </span><span class="token keyword" style="color:#00009f">INTEGER</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">REFERENCES</span><span class="token plain"> products</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    quantity </span><span class="token keyword" style="color:#00009f">INTEGER</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">CHECK</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">quantity </span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    total_amount </span><span class="token keyword" style="color:#00009f">NUMERIC</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">12</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">2</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ordered_at </span><span class="token keyword" style="color:#00009f">TIMESTAMP</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">NOT</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">NULL</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">;</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="agent-state--langgraph-workflow">Agent State + LangGraph Workflow<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#agent-state--langgraph-workflow" class="hash-link" aria-label="Direct link to Agent State + LangGraph Workflow" title="Direct link to Agent State + LangGraph Workflow" translate="no">​</a></h3>
<p>The state carries context across all nodes:</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/agent/state.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> typing </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Annotated</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> TypedDict</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> langgraph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">message </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> add_messages</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">AgentState</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">TypedDict</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    messages</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Annotated</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> add_messages</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    intent</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># "data_question" | "follow_up" | "general"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    sql</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    query_results</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    analysis</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    conversation_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><br></span></code></pre></div></div>
<p>The graph wires everything together. The LLM client points at LiteLLM -- the agent has no knowledge of which provider is serving completions:</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/agent/graph.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> functools </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> partial</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> langchain_openai </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> ChatOpenAI</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> langgraph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">graph </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> END</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> StateGraph</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">agent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">nodes </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    analyst_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> query_executor_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> responder_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    router_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> sql_generator_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">agent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">state </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> AgentState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> app</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">config </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> settings</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">_route_by_intent</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">state</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> AgentState</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    intent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"intent"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"general"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> intent </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"data_question"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"sql_generator"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> intent </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"follow_up"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"analyst"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"responder"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">build_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">db_session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> redis_client</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    llm </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ChatOpenAI</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        base_url</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">settings</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">litellm_base_url</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        api_key</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">settings</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">litellm_master_key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        model</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">settings</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">litellm_model</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        temperature</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> StateGraph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">AgentState</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"router"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> partial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">router_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> llm</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">llm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sql_generator"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> partial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sql_generator_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> llm</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">llm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"query_executor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> partial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        query_executor_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> db_session</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">db_session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> redis_client</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">redis_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"analyst"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> partial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">analyst_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> llm</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">llm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_node</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"responder"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> partial</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">responder_node</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> llm</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">llm</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">set_entry_point</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"router"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_conditional_edges</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"router"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> _route_by_intent</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sql_generator"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"query_executor"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"query_executor"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"analyst"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"analyst"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"responder"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_edge</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"responder"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> END</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> graph</span><span class="token punctuation" style="color:#393A34">.</span><span class="token builtin">compile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<!-- -->
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="sql-tool">SQL Tool<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#sql-tool" class="hash-link" aria-label="Direct link to SQL Tool" title="Direct link to SQL Tool" translate="no">​</a></h3>
<p>Read-only enforcement, keyword blocklist, and automatic row limits:</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/tools/sql_tool.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">FORBIDDEN_PATTERN </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> re</span><span class="token punctuation" style="color:#393A34">.</span><span class="token builtin">compile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">r"\b(INSERT|UPDATE|DELETE|DROP|ALTER|CREATE|TRUNCATE|GRANT|REVOKE|EXEC)\b"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    re</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">IGNORECASE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">_validate_sql</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sql</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    stripped </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> sql</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">strip</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">rstrip</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">";"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">not</span><span class="token plain"> stripped</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">upper</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">startswith</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"SELECT"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">raise</span><span class="token plain"> ValueError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Only SELECT queries are permitted."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> FORBIDDEN_PATTERN</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">search</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">stripped</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">raise</span><span class="token plain"> ValueError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Query contains forbidden keywords."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> stripped</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">query_database</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sql</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> redis_client</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    validated </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> _validate_sql</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">sql</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> redis_client</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        key </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"sql_cache:</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">hashlib</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">sha256</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">(</span><span class="token string-interpolation interpolation">validated</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">encode</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">(</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">)</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">)</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">hexdigest</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">(</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">)</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        cached </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> redis_client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> cached</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">cached</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    limited </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">validated</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c"> LIMIT </span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">settings</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">sql_row_limit</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> session</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">text</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">limited</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    rows </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">row</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">_mapping</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> row </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">fetchall</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> redis_client </span><span class="token keyword" style="color:#00009f">and</span><span class="token plain"> rows</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> redis_client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">setex</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">key</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> settings</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query_cache_ttl</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dumps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">rows</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> default</span><span class="token operator" style="color:#393A34">=</span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> rows</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="redis-memory">Redis Memory<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#redis-memory" class="hash-link" aria-label="Direct link to Redis Memory" title="Direct link to Redis Memory" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/memory/redis_store.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">load_conversation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conversation_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-interpolation string" style="color:#e3116c">f"conversation:</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">conversation_id</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> json</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">loads</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">data</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> data </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">save_conversation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conversation_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> messages</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">[</span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">setex</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string-interpolation string" style="color:#e3116c">f"conversation:</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">conversation_id</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        settings</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">conversation_ttl</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        json</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dumps</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">messages</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> default</span><span class="token operator" style="color:#393A34">=</span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="fastapi-routes">FastAPI Routes<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#fastapi-routes" class="hash-link" aria-label="Direct link to FastAPI Routes" title="Direct link to FastAPI Routes" translate="no">​</a></h3>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/api/routes.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token decorator annotation punctuation" style="color:#393A34">@router</span><span class="token decorator annotation punctuation" style="color:#393A34">.</span><span class="token decorator annotation punctuation" style="color:#393A34">post</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"/chat"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> response_model</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ChatResponse</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">chat</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    request</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> ChatRequest</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    db_session</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">Depends</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">get_db_session</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    redis_client</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">Depends</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">get_redis</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    history_data </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> load_conversation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">redis_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">conversation_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    history </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        HumanMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"content"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> m</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"role"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"human"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> AIMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"content"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> m </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> history_data</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    agent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> build_graph</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">db_session</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> redis_client</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> agent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ainvoke</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"messages"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> history </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">HumanMessage</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">content</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">message</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"intent"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"sql"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"query_results"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"analysis"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">""</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"conversation_id"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">conversation_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    all_messages </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"messages"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">await</span><span class="token plain"> save_conversation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">redis_client</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">conversation_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"role"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"human"</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token builtin">isinstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> HumanMessage</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"ai"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"content"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">content</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">         </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> m </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> all_messages</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    ai_response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token builtin">next</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">content </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> m </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token builtin">reversed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">all_messages</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token builtin">isinstance</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">m</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> AIMessage</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"I could not generate a response."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> ChatResponse</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">response</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">ai_response</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> conversation_id</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">request</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">conversation_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        sql</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"sql"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">or</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="mcp-server">MCP Server<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#mcp-server" class="hash-link" aria-label="Direct link to MCP Server" title="Direct link to MCP Server" translate="no">​</a></h3>
<p>Expose tools for external clients:</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">app/mcp/server.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token decorator annotation punctuation" style="color:#393A34">@server</span><span class="token decorator annotation punctuation" style="color:#393A34">.</span><span class="token decorator annotation punctuation" style="color:#393A34">list_tools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">async</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">list_tools</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Tool</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        Tool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"query_database"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             description</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"Execute a read-only SELECT query against the e-commerce database."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             inputSchema</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"object"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token string" style="color:#e3116c">"properties"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"sql"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"string"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token string" style="color:#e3116c">"required"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"sql"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        Tool</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"analyse_results"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             description</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"Compute summary statistics over data rows."</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">             inputSchema</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"object"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token string" style="color:#e3116c">"properties"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"rows"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"array"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"items"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"type"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"object"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                          </span><span class="token string" style="color:#e3116c">"required"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"rows"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><br></span></code></pre></div></div>
<p>Connect from Claude Desktop or Cursor:</p>
<div class="language-json codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-json codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token property" style="color:#36acaa">"mcpServers"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token property" style="color:#36acaa">"data-agent"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"command"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"python"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><span class="token property" style="color:#36acaa">"args"</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"-m"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"app.mcp.server"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="running-it">Running It<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#running-it" class="hash-link" aria-label="Direct link to Running It" title="Direct link to Running It" translate="no">​</a></h2>
<div class="language-bash codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-bash codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">git clone https://github.com/p-s-vishnu/data-agent.git</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cd data-agent</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">cp .env.example .env</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"># Add your LLM API key to .env</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">docker compose up --build</span><br></span></code></pre></div></div>
<p>Test:</p>
<div class="language-bash codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-bash codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST http://localhost:8000/api/chat \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -d '{"message": "What are the top 5 products by revenue?", "conversation_id": "demo-1"}'</span><br></span></code></pre></div></div>
<p>Follow-up (tests memory):</p>
<div class="language-bash codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-bash codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">curl -X POST http://localhost:8000/api/chat \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -H "Content-Type: application/json" \</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  -d '{"message": "Break that down by customer segment", "conversation_id": "demo-1"}'</span><br></span></code></pre></div></div>
<p>API docs at <a href="http://localhost:8000/docs" target="_blank" rel="noopener noreferrer" class="">http://localhost:8000/docs</a>.</p>
<hr>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="references">References<a href="https://www.vishnups.com/blog/building-a-data-analysis-agent#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h2>
<ol>
<li class=""><a href="https://www.anthropic.com/engineering/building-effective-agents" target="_blank" rel="noopener noreferrer" class="">Anthropic -- Building effective agents</a></li>
<li class=""><a href="https://github.com/NirDiamant/agents-towards-production" target="_blank" rel="noopener noreferrer" class="">NirDiamant -- Agents towards production</a></li>
<li class=""><a href="https://langchain-ai.github.io/langgraph/" target="_blank" rel="noopener noreferrer" class="">LangGraph documentation</a></li>
<li class=""><a href="https://docs.litellm.ai/" target="_blank" rel="noopener noreferrer" class="">LiteLLM documentation</a></li>
<li class=""><a href="https://modelcontextprotocol.io/" target="_blank" rel="noopener noreferrer" class="">Model Context Protocol</a></li>
<li class=""><a href="https://fastapi.tiangolo.com/" target="_blank" rel="noopener noreferrer" class="">FastAPI documentation</a></li>
<li class=""><a href="https://github.com/p-s-vishnu/data-agent" target="_blank" rel="noopener noreferrer" class="">Code: Companion code</a></li>
</ol>]]></content:encoded>
            <category>Agents</category>
            <category>LLM</category>
            <category>Software Engineering</category>
        </item>
        <item>
            <title><![CDATA[Learnings from Monzo: AWS reInvent A Deep Dive into Building a Digital Bank]]></title>
            <link>https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent</link>
            <guid>https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent</guid>
            <pubDate>Sat, 06 Jan 2024 00:00:00 GMT</pubDate>
            <description><![CDATA[Let’s take a sneak peek into the world of Monzo, the digital banking rocking around 8 million accounts, mostly in the UK. When they hit 4 million customers there were just eight tech folks on the infrastructure and reliability team running the show on AWS.]]></description>
            <content:encoded><![CDATA[<p>Let’s take a sneak peek into the world of Monzo, the digital banking rocking around 8 million accounts, mostly in the UK. When they hit 4 million customers there were just eight tech folks on the infrastructure and reliability team running the show on AWS.</p>
<p>I watched the&nbsp;<a href="https://www.youtube.com/watch?v=NTgB2z0E9ZU" target="_blank" rel="noopener noreferrer" class="">video</a>&nbsp;and read about the&nbsp;<a href="https://aws.amazon.com/solutions/case-studies/Monzo/" target="_blank" rel="noopener noreferrer" class="">case study</a>&nbsp;of Monzo and below are the key highlights extracted from them. I have added the pre-requisite and further reading topics in quotations.</p>
<p>The article is divided into two sections, For those who want the quick low-down, the TLDR has got you covered with the gist of the content but if you are up for a more in-depth explanation then the next one does that.</p>
<p><strong><em>Note:</em></strong>&nbsp;<em>Most of the screenshots are from the links above.</em></p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="tldr">TL;DR<a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#tldr" class="hash-link" aria-label="Direct link to TL;DR" title="Direct link to TL;DR" translate="no">​</a></h2>
<p>In a nutshell, the setup is humming 1500 micro-services and ~ 9000 pods in production as of 2019.</p>
<p><strong>Infra overview -</strong>&nbsp;Below are the tools and system architecture for the payment system</p>
<ol>
<li class=""><strong><em>Compute</em></strong>&nbsp;Data Centres (DCs) process incoming requests which get redirected to Micro-services running on&nbsp;<a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a>.</li>
<li class=""><strong><em>Data store:</em></strong>&nbsp;<a href="https://cassandra.apache.org/_/index.html" target="_blank" rel="noopener noreferrer" class="">Apache Cassandra</a>&nbsp;&amp; AWS S3 for persistent data storage</li>
<li class=""><strong><em>Monitoring and alerting:</em></strong>&nbsp;<a href="https://prometheus.io/docs/introduction/overview/" target="_blank" rel="noopener noreferrer" class="">Prometheus</a>&nbsp;for monitoring &amp; unlimited retention with&nbsp;<a href="https://thanos.io/" target="_blank" rel="noopener noreferrer" class="">Thanos</a></li>
<li class=""><strong><em>Distributed locking and coordination:</em></strong>&nbsp;<a href="https://etcd.io/" target="_blank" rel="noopener noreferrer" class="">etcd</a>&nbsp;cluster</li>
<li class=""><strong><em>Ordered Queuing:</em></strong>&nbsp;<a href="https://kafka.apache.org/" target="_blank" rel="noopener noreferrer" class="">Apache Kafka</a></li>
<li class=""><strong><em>Unordered queuing &amp; event publishing:</em></strong>&nbsp;<a href="https://nsq.io/" target="_blank" rel="noopener noreferrer" class="">NSQ</a></li>
</ol>
<p><img decoding="async" loading="lazy" alt="Monzo Infra" src="https://www.vishnups.com/assets/images/monzo-infra-95006c864eb51c8f32ae5c1675f700b4.png" width="2000" height="1160" class="img_dCa6"></p>
<p>What happens when a Payment request is initiated?</p>
<ol>
<li class="">The request for card usage is sent from the payment provider to Monzo’s DCs.</li>
<li class="">The request is then transferred to AWS and some requests would need a locking mechanism using etcd. Simultaneously, some will be sent to the Cassandra cluster for the data through the Kubernetes compute cluster.</li>
<li class="">If the transaction is approved then send back the response.</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Monzo Payment" src="https://www.vishnups.com/assets/images/monzo-payments-c8dc8c311b9debe253c6914ebb691aa3.png" width="781" height="649" class="img_dCa6"></p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="deep-dive">Deep Dive<a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#deep-dive" class="hash-link" aria-label="Direct link to Deep Dive" title="Direct link to Deep Dive" translate="no">​</a></h2>
<p>Six aspects of Monzo’s payment system will be discussed</p>
<ol>
<li class="">Data Centres</li>
<li class="">Compute</li>
<li class="">Data storage</li>
<li class="">Messaging</li>
<li class="">Locking</li>
<li class="">Monitoring</li>
</ol>
<p>Finally, the overall request-response process.</p>
<p><img decoding="async" loading="lazy" alt="Monzo Deep Dive" src="https://www.vishnups.com/assets/images/monzo-deep-dive-0bc9f5dc48584b006700d13433c3060b.png" width="2000" height="529" class="img_dCa6"></p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="1-data-centres">1. Data Centres<a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#1-data-centres" class="hash-link" aria-label="Direct link to 1. Data Centres" title="Direct link to 1. Data Centres" translate="no">​</a></h2>
<blockquote>
<p><strong>What is AWS Direct Connect?</strong><br>
<!-- -->It serves as a bridge between an internal network (on-prem) to an AWS Direct Connect location (AWS services e.g. Amazon S3 or Amazon VPC).</p>
</blockquote>
<p>The necessity for a data centre arises from the limitation posed by payment providers like&nbsp;<a href="https://www.mastercard.co.uk/en-gb/html" target="_blank" rel="noopener noreferrer" class="">Mastercard</a>&nbsp;and&nbsp;<a href="https://www.starlingbank.com/resources/banking/guide-to-faster-payments/" target="_blank" rel="noopener noreferrer" class="">Faster Payments</a>&nbsp;which exclusively provide optical fibre and lack integration capability with cloud providers.</p>
<p><strong>Request flow:</strong></p>
<ol>
<li class=""><em>Ingress from the service provider:</em>&nbsp;The journey commences with a message inbound from the service provider.</li>
<li class=""><em>Monzo’s Data Centre:</em>&nbsp;The message traverses through Monzo’s data centre, where it undergoes encryption and is channelled into a Virtual Private Network (VPN) through AWS Direct Connect.</li>
<li class="">Finally reaches the Kubernetes(K8s) cluster where it gets authenticated and passes through multiple micro-services.</li>
</ol>
<p><img decoding="async" loading="lazy" alt="Monzo Data Centre" src="https://www.vishnups.com/assets/images/monzo-data-centre-84f74b5c78c4cf3d44bcef541a562aa0.png" width="2000" height="945" class="img_dCa6"></p>
<p><strong>Response:</strong> It follows a similar reverse path and is returned to the terminal.</p>
<p>If you want to know how Monzo secures its application for IP compliance you can read the article - <a href="https://monzo.com/blog/2022/03/31/how-we-secure-monzos-banking-platform" target="_blank" rel="noopener noreferrer" class="">How we secure Monzo’s banking platform</a>.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="2-compute">2. Compute<a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#2-compute" class="hash-link" aria-label="Direct link to 2. Compute" title="Direct link to 2. Compute" translate="no">​</a></h2>
<p>As mentioned earlier, there is a fleet of 1500 micro-services and ~ 9000 pods in production as of 2019 mostly in single region&nbsp;<code>eu-west-1</code>.</p>
<p>The question arises: How are they able to run so many nodes in the cluster?</p>
<ul>
<li class="">It converges to one reason - consistency. Across teams, the company upholds a uniformity of language, design patterns, and infrastructure. This enables the orchestration of a multitude of nodes seamlessly.</li>
<li class="">Additionally, all the code is written in Go which helps reduce the docker image size and expedites the container creation process.</li>
</ul>
<p>For context, the below is not a neural network but rather micro-services running and communicating on a single day.</p>
<p><img decoding="async" loading="lazy" alt="Monzo Compute" src="https://www.vishnups.com/assets/images/monzo-compute-b13c3de36b9a488df4336bd1ae2d26f6.png" width="2000" height="1121" class="img_dCa6"></p>
<p>The shipper is the tool employed at Monzo to build, validate and roll out deployments to the cluster.</p>
<p><img decoding="async" loading="lazy" alt="Monzo Shipper" src="https://www.vishnups.com/assets/images/monzo-shipper-849b3b299272e338a6c9f9df4edd75d4.png" width="2000" height="967" class="img_dCa6"></p>
<p>A typical deployment command looks like below and there are hundreds of similar deployments done in a day.</p>
<p><img decoding="async" loading="lazy" alt="Monzo Deployment" src="https://www.vishnups.com/assets/images/monzo-deployment-0f0d062f70d30139f4c9f88e608400bf.png" width="2000" height="1291" class="img_dCa6"></p>
<p><strong>Service discovery</strong>&nbsp;using Envoy</p>
<blockquote>
<p><a href="https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy" target="_blank" rel="noopener noreferrer" class=""><strong>Envoy</strong></a><strong>:</strong>&nbsp;serves as a versatile software, functioning as a service proxy/mesh to govern and oversee both inbound and outbound traffic for all services within the service mesh.</p>
</blockquote>
<ul>
<li class="">Since there are numerous deployments, it becomes important to devise a mechanism for the services to find and communicate with one another, this is solved using envoy and custom logic called envoy config provider.</li>
<li class="">The config provider monitors state changes in the K8s API server and subsequently, it orchestrates updates across all proxy processes and lets them know what to find where.</li>
</ul>
<p><img decoding="async" loading="lazy" alt="Monzo Envoy" src="https://www.vishnups.com/assets/images/monzo-envoy-5c0ac15dfe76dac53a2b830f1cca467e.png" width="2000" height="1062" class="img_dCa6"></p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="3-data-storage"><strong>3. Data Storage</strong><a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#3-data-storage" class="hash-link" aria-label="Direct link to 3-data-storage" title="Direct link to 3-data-storage" translate="no">​</a></h2>
<blockquote>
<p><strong>How does Cassandra work?</strong><br>
<!-- -->Cassandra operates as a Masterless distributed database, it has nodes that are joined to form a ring ⇒ Data spans across these interconnected rings.<br>
<!-- -->Operations like reading happen using a load-balancing mechanism like round-robin and the client remains oblivious to the data’s actual whereabouts. Read more&nbsp;<a href="https://cassandra.apache.org/_/cassandra-basics.html" target="_blank" rel="noopener noreferrer" class="">here</a></p>
</blockquote>
<p>Account data is stored in the NoSQL Cassandra database and all the log archives are stored in the S3 bucket. It is running outside of the K8s cluster on the Ec2 instance.</p>
<p>To fine-tune the database’s response time and consistency, replication and Quorum mechanisms come into play. For instance, if a need for a faster response arises, adjusting the replication factor becomes the strategy, albeit with the understanding that this may come at the cost of reduced consistency.</p>
<p>Delving into the team’s routine practices, certain exercises involve restarting the database cluster one node at a time. This deliberate action serves as a litmus test, assessing the resilience and robustness of the database in real-world scenarios.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="4-messaging"><strong>4. Messaging</strong><a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#4-messaging" class="hash-link" aria-label="Direct link to 4-messaging" title="Direct link to 4-messaging" translate="no">​</a></h2>
<blockquote>
<p>**What is event-driven architecture?<br>
<!-- -->**A paradigm, where different components of a system communicate with each other through events. An event can be any occurrence or change in the system that requires attention. These events can be generated by users, applications, or external systems.</p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Monzo Messaging" src="https://www.vishnups.com/assets/images/monzo-messaging-08fa874bf42b1653e128e06dbe28543c.png" width="2000" height="1033" class="img_dCa6"></p>
<p>A lot of computing works asynchronously, like an Event-driven architecture so messaging systems were introduced. In this system, Kafka is used for ordered queuing while NSQ is for unordered &amp; event publishing scenarios. These threads provide interesting content about Kafka vs NSQ (<a href="https://news.ycombinator.com/item?id=14455919" target="_blank" rel="noopener noreferrer" class="">link1</a>,&nbsp;<a href="https://gcore.com/learning/nats-rabbitmq-nsq-kafka-comparison/" target="_blank" rel="noopener noreferrer" class="">link2</a>)</p>
<p>Push notification is one scenario where asynchronous messaging is used. Whenever a customer makes a successful purchase or a vendor requests approval for payment a notification is instantaneously sent to the customer’s app.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="5-locking"><strong>5. Locking</strong><a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#5-locking" class="hash-link" aria-label="Direct link to 5-locking" title="Direct link to 5-locking" translate="no">​</a></h2>
<blockquote>
<p><strong>What are AWS I3 instances?</strong><br>
<!-- -->Amazon EC2 I3 instances are Storage Optimised instances for high transaction, low latency workloads. I3 instances offer a good price per I/O performance for workloads such as NoSQL databases, in-memory databases, data warehousing, Elastic search, and analytics workloads.</p>
<p>**What is etcd?<br>
<!-- -->**Distributed, highly available, key-value store. High throughput and low latency locking. It works akin to Cassandra however unlike the former it has a master selection process.</p>
</blockquote>
<p>Given the distributed nature, there are instances where mutual exclusivity and locking become imperative. Here,&nbsp;<strong>etcd</strong>&nbsp;providing distributed locking capabilities. Without proper locking, concurrent modifications can lead to inconsistent or corrupted data. Locks ensure that only one process can modify the data at a time, maintaining its integrity.</p>
<p>Additionally, running the setup on AWS I3 infrastructure guarantees better performance.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="6-monitoring"><strong>6. Monitoring</strong><a href="https://www.vishnups.com/blog/2024/01/06/Monzo-AWS-reInvent#6-monitoring" class="hash-link" aria-label="Direct link to 6-monitoring" title="Direct link to 6-monitoring" translate="no">​</a></h2>
<blockquote>
<p><strong>Prometheus</strong>&nbsp;is a Time series data store and query engine</p>
<p><strong>Thanos</strong>&nbsp;is a highly available Prometheus setup providing infinite retention capabilities.</p>
<p><strong>Sidecar pattern:</strong>&nbsp;The Sidecar pattern is a design pattern used in micro-services architecture. It involves running a separate process or container alongside the main application to enhance its functionality. Think of it like a sidecar attached to a motorcycle; the sidecar provides additional features to the bike.&nbsp;<a href="https://learn.microsoft.com/en-us/azure/architecture/patterns/sidecar" target="_blank" rel="noopener noreferrer" class="">Read more</a></p>
</blockquote>
<p><img decoding="async" loading="lazy" alt="Monzo Monitoring" src="https://www.vishnups.com/assets/images/monzo-monitoring-ea74df3a061af019318f1ace7b3ec7f8.png" width="2054" height="1150" class="img_dCa6"></p>
<p>Prometheus is “shared out” to various functional domains with two replicas each to handle failures, the collected time series data is “ephemeral “ (only 24 hours of storage). This begs two requirements for the monitoring system.</p>
<p>Users necessitate an effortless means to query logs, preferably centralised for comprehensive search capabilities.
The logs should be saved for longer than 24 hours.
Solution - Thanos as a sidecar to the Prometheus servers</p>
<p>Emulates multiple Prometheus servers’ query search as a single one with Thanos. It uses Thanos query which fans out to all the sidecar applications retrieving the location of the requested data i.e. parallely searching for the requested data.
To meet the second requirement, Thanos takes periodic strides, saving data to the S3 bucket, ensuring a repository that surpasses the 24-hour timeframe
Beyond this, an array of metrics are monitored by the system like request metrics, low-level system metrics, business logic, social media trends, etc. Hence, various Alert managers are created using Prometheus to detect anomalies and observe trends.</p>]]></content:encoded>
            <category>MLOps</category>
            <category>Use Case</category>
        </item>
        <item>
            <title><![CDATA[Part 2: How to frame an ML problem?]]></title>
            <link>https://www.vishnups.com/blog/2022/07/25/how-to-frame-an-ml-problem-part2</link>
            <guid>https://www.vishnups.com/blog/2022/07/25/how-to-frame-an-ml-problem-part2</guid>
            <pubDate>Mon, 25 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[The article will be covering the risks of ML and Google’s responsible AI practices. This article has a predecessor, for a better understanding, I would recommend you have a look at the previous article.]]></description>
            <content:encoded><![CDATA[<p>The article will be covering the risks of ML and Google’s responsible AI practices. This article has a predecessor, for a better understanding, I would recommend you have a look at the previous article.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="read-complete-article-here"><a href="https://medium.com/@psvishnu/how-to-frame-an-ml-problem-2-2-4490d85bb562" target="_blank" rel="noopener noreferrer" class="">Read complete article here</a><a href="https://www.vishnups.com/blog/2022/07/25/how-to-frame-an-ml-problem-part2#read-complete-article-here" class="hash-link" aria-label="Direct link to read-complete-article-here" title="Direct link to read-complete-article-here" translate="no">​</a></h2>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Part 1: How to frame an ML problem?]]></title>
            <link>https://www.vishnups.com/blog/2022/07/14/how-to-frame-an-ml-problem-part1</link>
            <guid>https://www.vishnups.com/blog/2022/07/14/how-to-frame-an-ml-problem-part1</guid>
            <pubDate>Thu, 14 Jul 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[The article is my attempt to capture Section 1- “Frame ML problems” of the Professional Machine Learning Engineer (PMLE) certification exam. Even though the topics are aligned to PMLE, readers who are interested to know about defining business challenges as an ML use case, establishing success criteria, and mitigating risks of ML solutions will also find it useful.]]></description>
            <content:encoded><![CDATA[<p>The article is my attempt to capture&nbsp;<strong>Section 1- “Frame ML problems”</strong>&nbsp;of the Professional Machine Learning Engineer (PMLE) certification exam. Even though the topics are aligned to PMLE, readers who are interested to know about defining business challenges as an ML use case, establishing success criteria, and mitigating risks of ML solutions will also find it useful.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="read-complete-article-here"><a href="https://medium.com/@psvishnu/how-to-frame-an-ml-problem-1-2-b6380cdd8b64" target="_blank" rel="noopener noreferrer" class="">Read complete article here</a><a href="https://www.vishnups.com/blog/2022/07/14/how-to-frame-an-ml-problem-part1#read-complete-article-here" class="hash-link" aria-label="Direct link to read-complete-article-here" title="Direct link to read-complete-article-here" translate="no">​</a></h2>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Online prediction using GCP’s Vertex AI]]></title>
            <link>https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai</link>
            <guid>https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai</guid>
            <pubDate>Sun, 22 May 2022 00:00:00 GMT</pubDate>
            <description><![CDATA[Serve and process real-time data with a Tensorflow model using Pub-Sub, Cloud Dataflow, BigQuery and Vertex AI.]]></description>
            <content:encoded><![CDATA[<p>Serve and process real-time data with a Tensorflow model using Pub-Sub, Cloud Dataflow, BigQuery and Vertex AI.</p>
<p>In this project, we are predicting the travel fare when a user books a cab. Unlike traditional pricing calculation, here the price is calculated dynamically based on multiple parameters, including the feature <strong>number of trips in the last 5 minutes</strong>, which acts as a proxy for real-time traffic.</p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="table-of-content">Table of Content<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#table-of-content" class="hash-link" aria-label="Direct link to Table of Content" title="Direct link to Table of Content" translate="no">​</a></h2>
<ol>
<li class="">Architecture</li>
<li class="">Data Ingestion</li>
<li class="">Model Deployment</li>
<li class="">Prediction</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="1-architecture">1. Architecture<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#1-architecture" class="hash-link" aria-label="Direct link to 1. Architecture" title="Direct link to 1. Architecture" translate="no">​</a></h2>
<p><img decoding="async" loading="lazy" alt="GCP’s ASL repository" src="https://www.vishnups.com/assets/images/vertexai-architecture-a59a225fd77db70ed43c6565a61c3542.png" width="1400" height="847" class="img_dCa6"></p>
<p>The whole system can be divided into two parts</p>
<ol>
<li class="">Ingesting continuous feed of taxi trip data</li>
<li class="">Predicting on-demand fare requests</li>
</ol>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="2-data-ingestion">2. Data Ingestion<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#2-data-ingestion" class="hash-link" aria-label="Direct link to 2. Data Ingestion" title="Direct link to 2. Data Ingestion" translate="no">​</a></h2>
<p>For the data ingestion part, we will need Pub/Sub, Dataflow and Big query. Let's configure the required services one by one.</p>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="pub-sub">Pub-Sub<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#pub-sub" class="hash-link" aria-label="Direct link to Pub-Sub" title="Direct link to Pub-Sub" translate="no">​</a></h3>
<blockquote>
<p>Pub/Sub is used for streaming analytics and data integration pipelines to ingest and distribute data. It is equally effective as a messaging-oriented middleware for service integration or as a queue to parallelize tasks. <a href="https://cloud.google.com/pubsub/docs/overview#core_concepts" target="_blank" rel="noopener noreferrer" class="">Read more about the core concepts like - topics, subscription, publisher, etc.</a></p>
</blockquote>
<p>Here Pub/Sub will be used as a messaging bus that receives and stores recently completed taxi trips.</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">pubsub.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> logging</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> api_core</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cloud </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> pubsub_v1 </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> pubsub</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">get_pubsub_client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">gcp_project_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> topic</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxi_rides"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">""" Get topic if already exists or else create a new one</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    """</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    publisher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pubsub</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">PublisherClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    topic_name </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">topic_path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">gcp_project_id</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> topic</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">get_topic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">topic_name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Reusing pub/sub topic %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> topic</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">except</span><span class="token plain"> api_core</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exceptions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">NotFound</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">create_topic</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">topic_name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Creating pub/sub topic %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> topic</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> publisher</span><br></span></code></pre></div></div>
<p>Since we cannot get live taxi trip data we will create a python script that randomly generates trip data and pushes it to the Pub/Sub.</p>
<div class="language-shell codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-shell codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">PROJECT_ID=$(gcloud config get-value project)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">REGION=$(gcloud config get-value ai/region)</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">BUCKET=$PROJECT_ID # change as necessary</span><br></span></code></pre></div></div>
<p>Run the following code as a separate script, it is configured to send about 2,000 trip messages every five minutes with some randomness in the frequency to mimic traffic fluctuations. These numbers come from looking at the historical average of taxi ride frequency in BigQuery.</p>
<p>In production this script would be replaced with actual taxis with IoT devices sending trip data to Cloud Pub/Sub.</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">publisher </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> get_pubsub_client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">PROJECT_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> topic</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxi_rides"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">while</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">True</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  num_trips </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> random</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">randint</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">10</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">60</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> i </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> </span><span class="token builtin">range</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">num_trips</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    publisher</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">publish</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">topic_name</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">b"taxi_ride"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Publishing: %s"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> time</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ctime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  time</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">sleep</span><span class="token punctuation" style="color:#393A34">(</span><span class="token number" style="color:#36acaa">5</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="big-query">Big Query<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#big-query" class="hash-link" aria-label="Direct link to Big Query" title="Direct link to Big Query" translate="no">​</a></h3>
<blockquote>
<p>Big Query is a Data warehouse managed by google to store, process, analyse, and visualize large amounts of data. <a href="https://cloud.google.com/bigquery/docs/introduction" target="_blank" rel="noopener noreferrer" class="">Link to read more</a>.</p>
</blockquote>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">bigquery.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> logging</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> api_core</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cloud </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> bigquery</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">create_dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataset_id</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxifare"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    bq </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    dataset </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bq</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataset_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        bq</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">create_dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataset</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># will fail if dataset already exists</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Dataset created."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">except</span><span class="token plain"> api_core</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exceptions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Conflict</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Dataset already exists."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">create_table</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataset_id</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxifare"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> table_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"traffic_realtime"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    bq </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    dataset </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">bq</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dataset</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">dataset_id</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    table_ref </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> dataset</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">table</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">table_name</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SCHEMA </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SchemaField</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"trips_last_5min"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"INTEGER"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mode</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"REQUIRED"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SchemaField</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"time"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"TIMESTAMP"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mode</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"REQUIRED"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    table </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Table</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">table_ref</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> schema</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">SCHEMA</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">try</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        bq</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">create_table</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">table</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Table created."</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">except</span><span class="token plain"> api_core</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">exceptions</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Conflict</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Table already exists."</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="dataflow">Dataflow<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#dataflow" class="hash-link" aria-label="Direct link to Dataflow" title="Direct link to Dataflow" translate="no">​</a></h3>
<blockquote>
<p><a href="https://www.youtube.com/watch?v=XdsuDOQ9nkU&amp;ab_channel=GoogleCloudTech" target="_blank" rel="noopener noreferrer" class="">Dataflow</a> is a fast, <a href="https://www.youtube.com/watch?v=vxJobGtqKVM&amp;ab_channel=IBMTechnology" target="_blank" rel="noopener noreferrer" class="">serverless</a> service for executing batch and streaming data processing pipelines. You create your pipelines with Apache Beam and then run them using the Dataflow service.
<a href="https://beam.apache.org/documentation/basics/" target="_blank" rel="noopener noreferrer" class="">Link to basics of Apache beam</a> &amp; <a href="https://cloud.google.com/dataflow" target="_blank" rel="noopener noreferrer" class="">Link to read more about Dataflow</a>.</p>
</blockquote>
<p>Now that our taxi data is pushed to Pub/Sub, and our BigQuery table is set up, let’s consume the Pub/Sub data using a streaming DataFlow pipeline.</p>
<p>Dataflow will be responsible for the following transformations:</p>
<ol>
<li class="">Pull the completed trips from the Pub/Sub</li>
<li class="">Window the messages (every 5 mins)</li>
<li class="">Count the number of messages in the window</li>
<li class="">Format the count for BigQuery</li>
<li class="">Write results to BigQuery table</li>
</ol>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">dataflow.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> argparse</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> datetime </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> datetime</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> apache_beam </span><span class="token keyword" style="color:#00009f">as</span><span class="token plain"> beam</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> apache_beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">options</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pipeline_options </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    GoogleCloudOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    PipelineOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    SetupOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    StandardOptions</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> apache_beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">transforms </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> window  </span><span class="token comment" style="color:#999988;font-style:italic"># pylint: disable=unused-import</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token class-name">CountFn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">CombineFn</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">"""Counter function to accumulate statistics"""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">create_accumulator</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">self</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">0</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">add_input</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> element</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">del</span><span class="token plain"> element</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> count </span><span class="token operator" style="color:#393A34">+</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">merge_accumulators</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> accumulators</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token builtin">sum</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">accumulators</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">extract_output</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">self</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> count</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">argv</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">None</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">"""Build and run the pipeline."""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parser </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> argparse</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ArgumentParser</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_argument</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--project"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">help</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Google Cloud Project ID"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> required</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_argument</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"--region"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">help</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Google Cloud region"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> required</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">True</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">add_argument</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token string" style="color:#e3116c">"--input_topic"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token builtin">help</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"Google Cloud PubSub topic name "</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        required</span><span class="token operator" style="color:#393A34">=</span><span class="token boolean" style="color:#36acaa">True</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    known_args</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pipeline_args </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> parser</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">parse_known_args</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">argv</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_options </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> PipelineOptions</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">pipeline_args</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_options</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">view_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">SetupOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">save_main_session </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_options</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">view_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">StandardOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">streaming </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token boolean" style="color:#36acaa">True</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_options</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">view_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">GoogleCloudOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">region </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> known_args</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">region</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_options</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">view_as</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">GoogleCloudOptions</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">project </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> known_args</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">project</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    p </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Pipeline</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">options</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">pipeline_options</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    topic </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"projects/</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">known_args</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">project</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">/topics/</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">known_args</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">input_topic</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># this table needs to exist</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    table_spec </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">known_args</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">project</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">:taxifare.traffic_realtime"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">to_bq_format</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">count</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token triple-quoted-string string" style="color:#e3116c">"""BigQuery writer requires rows to be stored as python dictionary"""</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"trips_last_5min"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> count</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token string" style="color:#e3116c">"time"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> datetime</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">now</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">strftime</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"%Y-%m-%d %H:%M:%S"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># noqa F841 pylint: disable=unused-variable</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        p</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"read_from_pubsub"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ReadFromPubSub</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">topic</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">topic</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">with_output_types</span><span class="token punctuation" style="color:#393A34">(</span><span class="token builtin">bytes</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"window"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WindowInto</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">window</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SlidingWindows</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">size</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">300</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> period</span><span class="token operator" style="color:#393A34">=</span><span class="token number" style="color:#36acaa">15</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"count"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">CombineGlobally</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">CountFn</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">without_defaults</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"format_for_bq"</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Map</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">to_bq_format</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">|</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"write_to_bq"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token operator" style="color:#393A34">&gt;&gt;</span><span class="token plain"> beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WriteToBigQuery</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            table_spec</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic"># WRITE_TRUNCATE not supported for streaming</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            write_disposition</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">BigQueryDisposition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WRITE_APPEND</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            create_disposition</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">beam</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">io</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">BigQueryDisposition</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">CREATE_NEVER</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># result.wait_until_finish() #only do this if running with DirectRunner</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> p</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># noqa F841 pylint: disable=unused-variable</span><br></span></code></pre></div></div>
<p>Launch the dataflow pipeline using the command below.</p>
<div class="language-shell codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-shell codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">python3 dataflow.py --input_topic taxi_rides --runner=DataflowRunner --project=$PROJECT_ID --region=$REGION --temp_location=gs://$BUCKET/dataflow_streaming</span><br></span></code></pre></div></div>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="3-model-deployment">3. Model Deployment<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#3-model-deployment" class="hash-link" aria-label="Direct link to 3. Model Deployment" title="Direct link to 3. Model Deployment" translate="no">​</a></h2>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="vertex-ai">Vertex AI<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#vertex-ai" class="hash-link" aria-label="Direct link to Vertex AI" title="Direct link to Vertex AI" translate="no">​</a></h3>
<blockquote>
<p><a href="https://www.youtube.com/watch?v=gT4qqHMiEpA&amp;ab_channel=GoogleCloudTech" target="_blank" rel="noopener noreferrer" class="">Vertex AI</a>&nbsp;is a Jupyter-based fully managed, scalable, enterprise-ready compute infrastructure with security controls and user management capabilities. It serves as a one-stop environment to complete all of the ML work, from experimentation to deployment, to managing and monitoring models.&nbsp;<a href="https://cloud.google.com/vertex-ai" target="_blank" rel="noopener noreferrer" class="">Link to read more</a></p>
</blockquote>
<p>For keeping the article short, I have refrained from explaining the training code. The code can be found in the below GitHub repo. Do let me know in the comments if an explanation of the training code would help.</p>
<p><img decoding="async" loading="lazy" alt="Vertex AI Pipeline" src="https://www.vishnups.com/assets/images/vertexai-pipeline-8b601ffe899e82f7c31009d43d0f9b82.png" width="1240" height="1034" class="img_dCa6"></p>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="kubeflow-pipeline">Kubeflow pipeline<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#kubeflow-pipeline" class="hash-link" aria-label="Direct link to Kubeflow pipeline" title="Direct link to Kubeflow pipeline" translate="no">​</a></h3>
<blockquote>
<p><a href="https://www.youtube.com/watch?v=cTZArDgbIWw&amp;ab_channel=GoogleCloudTech" target="_blank" rel="noopener noreferrer" class="">Kubeflow</a>&nbsp;is known as the ML toolkit for&nbsp;<a href="https://kubernetes.io/" target="_blank" rel="noopener noreferrer" class="">Kubernetes</a>. The project is dedicated to making deployments of Machine Learning (ML) workflows on Kubernetes simple, portable, and scalable. The goal is to provide a straightforward way to deploy best-of-breed open-source systems for ML in diverse infrastructures.<br>
<a href="https://www.kubeflow.org/docs/started/architecture/" target="_blank" rel="noopener noreferrer" class="">Link to read more</a></p>
</blockquote>
<p>We will make our prediction service available now. For that, we will be wrapping the following processes as a kubeflow pipeline.</p>
<ol>
<li class=""><strong>Model training:</strong>&nbsp;Based on the latest labelled data start the model training as a serverless job.</li>
<li class=""><strong>Upload model:</strong>&nbsp;The output of the trained model will be transferred to Google cloud storage.</li>
<li class=""><strong>Create endpoint:</strong>&nbsp;While the model is being trained create an endpoint for the same asynchronously.</li>
<li class=""><strong>Deployment:</strong>&nbsp;Finally deploy the model to the created endpoint.</li>
</ol>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">train_upload_deploy_pipeline.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> kfp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">v2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">dsl </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> component</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> pipeline</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> kfp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">v2</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">google </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> experimental</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google_cloud_pipeline_components</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">aiplatform </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> ModelUploadOp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> EndpointCreateOp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ModelDeployOp</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:#393A34">@component</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">training_op</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">input1</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">print</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-interpolation string" style="color:#e3116c">f"VertexAI pipeline: </span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">input1</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token decorator annotation punctuation" style="color:#393A34">@pipeline</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxifare--train-upload-endpoint-deploy"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">pipeline</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    project</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> PROJECT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    model_display_name</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> MODEL_DISPLAY_NAME</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 1. Model Training</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    train_task </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> training_op</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"taxifare training pipeline"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    experimental</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run_as_aiplatform_custom_job</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        train_task</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        display_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"pipelines-train-</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">TIMESTAMP</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        worker_pool_specs</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"pythonPackageSpec"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"executor_image_uri"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> PYTHON_PACKAGE_EXECUTOR_IMAGE_URI</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"package_uris"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">PYTHON_PACKAGE_URIS</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"python_module"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> PYTHON_MODULE</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"args"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--eval_data_path=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">EVAL_DATA_PATH</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--output_dir=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">OUTDIR</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--train_data_path=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">TRAIN_DATA_PATH</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--batch_size=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">BATCH_SIZE</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--num_examples_to_train_on=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">NUM_EXAMPLES_TO_TRAIN_ON</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic"># noqa: E501</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--num_evals=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">NUM_EVALS</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--nbuckets=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">NBUCKETS</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--lr=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">LR</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                        </span><span class="token string-interpolation string" style="color:#e3116c">f"--nnsize=</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">NNSIZE</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"replica_count"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">REPLICA_COUNT</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token string" style="color:#e3116c">"machineSpec"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                    </span><span class="token string" style="color:#e3116c">"machineType"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">MACHINE_TYPE</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">                </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 2. Model Upload</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    model_upload_op </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ModelUploadOp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        project</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">PROJECT</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        display_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"pipelines-ModelUpload-</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">TIMESTAMP</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        artifact_uri</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">OUTDIR</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">/savedmodel"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        serving_container_image_uri</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">SERVING_CONTAINER_IMAGE_URI</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        serving_container_environment_variables</span><span class="token operator" style="color:#393A34">=</span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"NOT_USED"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"NO_VALUE"</span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    model_upload_op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">after</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">train_task</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 3. Create Endpoint</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    endpoint_create_op </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> EndpointCreateOp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        project</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">PROJECT</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        display_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"pipelines-EndpointCreate-</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">TIMESTAMP</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># 4. Deployment</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    model_deploy_op </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> ModelDeployOp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        project</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">PROJECT</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        endpoint</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">endpoint_create_op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">outputs</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"endpoint"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        model</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">model_upload_op</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">outputs</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"model"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        deployed_model_display_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">MODEL_DISPLAY_NAME</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        machine_type</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">MACHINE_TYPE</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic"># Compile the pipeline</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> kfp</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">v2 </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> compiler</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">not</span><span class="token plain"> os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">path</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">isdir</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"vertex_pipelines"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    os</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">mkdir</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"vertex_pipelines"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">compiler</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Compiler</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token builtin">compile</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_func</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">pipeline</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    package_path</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"./vertex_pipelines/train_upload_endpoint_deploy.json"</span><span class="token punctuation" style="color:#393A34">,</span><br></span></code></pre></div></div>
<p>If the compilation is successful then you can run the following code and your pipeline will start running.</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">run_kfpipeline.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"># Run the pipeline</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google_cloud_pipeline_components </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> aiplatform</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pipeline_job </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> aiplatform</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">pipeline_jobs</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">PipelineJob</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    display_name</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxifare_pipeline"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    template_path</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"./vertex_pipelines/train_upload_endpoint_deploy.json"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    pipeline_root</span><span class="token operator" style="color:#393A34">=</span><span class="token string-interpolation string" style="color:#e3116c">f"</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">PIPELINE_ROOT</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    project</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">PROJECT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    location</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">REGION</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">pipeline_job</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">run</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<p>Once the pipeline starts, head to Vertex AI &gt; Pipeline and you should be able to see the pipeline similar to the below screenshot.</p>
<p><img decoding="async" loading="lazy" alt="Vertex AI Pipeline" src="https://www.vishnups.com/assets/images/vertexai-pipeline-8b601ffe899e82f7c31009d43d0f9b82.png" width="1240" height="1034" class="img_dCa6"></p>
<h2 class="anchor anchorTargetStickyNavbar_xRYd" id="4-prediction">4. Prediction<a href="https://www.vishnups.com/blog/online-prediction-using-gcp-vertex-ai#4-prediction" class="hash-link" aria-label="Direct link to 4. Prediction" title="Direct link to 4. Prediction" translate="no">​</a></h2>
<p>From the previous step, save the endpoint(ENDPOINT) where our model is deployed. We need only two more components to make this system complete.</p>
<ol>
<li class="">A function that would fetch the last 5 min traffic and add it as a feature to the request.</li>
<li class="">Another function is to pass on the modified request, create the prediction service client and present the result.</li>
</ol>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockTitle_iEPX">fare_prediction.py</div><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> logging</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> typing </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Dict</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> List</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Union</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">cloud </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> aiplatform</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> bigquery</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">protobuf </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> json_format</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">from</span><span class="token plain"> google</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">protobuf</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">struct_pb2 </span><span class="token keyword" style="color:#00009f">import</span><span class="token plain"> Value</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">add_traffic_last_5min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> dataset</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"taxifare"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> table</span><span class="token operator" style="color:#393A34">=</span><span class="token string" style="color:#e3116c">"traffic_realtime"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">""" Adds the dynamic feature `traffic_last_5min` to the instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    """</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    bq </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bigquery</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Client</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    query_string </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-interpolation string" style="color:#e3116c">f"""</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">    SELECT</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">      *</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">    FROM</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">      `</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">dataset</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">.</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">table</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">`</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">    ORDER BY</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">      time DESC</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">    LIMIT 1</span><br></span><span class="token-line" style="color:#393A34"><span class="token string-interpolation string" style="color:#e3116c">    """</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    trips </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bq</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">query_string</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">to_dataframe</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"trips_last_5min"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">[</span><span class="token number" style="color:#36acaa">0</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    instance</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string" style="color:#e3116c">"traffic_last_5min"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token builtin">int</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">trips</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">def</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">predict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    project</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    endpoint_id</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    instances</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> Union</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Dict</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> List</span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">Dict</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">]</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    location</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"us-central1"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    api_endpoint</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token builtin">str</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string" style="color:#e3116c">"us-central1-aiplatform.googleapis.com"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token triple-quoted-string string" style="color:#e3116c">"""</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    `instances` can be either single instance of type dict or a list</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    of instances.</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    Reference: https://github.com/googleapis/python-aiplatform/blob/master/samples/snippets/predict_custom_trained_model_sample.py</span><br></span><span class="token-line" style="color:#393A34"><span class="token triple-quoted-string string" style="color:#e3116c">    """</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    client_options </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token string" style="color:#e3116c">"api_endpoint"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> api_endpoint</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain">     </span><span class="token comment" style="color:#999988;font-style:italic"># f"{REGION}-aiplatform.googleapis.com"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    client </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> aiplatform</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">gapic</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">PredictionServiceClient</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">client_options</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">client_options</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    instances </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> instances </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token builtin">type</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instances</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">==</span><span class="token plain"> </span><span class="token builtin">list</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">instances</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    instances </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain">add_traffic_last_5min</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance_dict</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> instance_dict </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> instances</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    instances </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        json_format</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ParseDict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">instance_dict</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> instance_dict </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> instances</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parameters_dict </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    parameters </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> json_format</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">ParseDict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">parameters_dict</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> Value</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    endpoint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">endpoint_path</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        project</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">project</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> location</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">location</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> endpoint</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">endpoint_id</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    response </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> client</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">predict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        endpoint</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">endpoint</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> instances</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">instances</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> parameters</span><span class="token operator" style="color:#393A34">=</span><span class="token plain">parameters</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">"response"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-interpolation string" style="color:#e3116c">f" deployed_model_id: </span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">{</span><span class="token string-interpolation interpolation">response</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">.</span><span class="token string-interpolation interpolation">deployed_model_id</span><span class="token string-interpolation interpolation punctuation" style="color:#393A34">}</span><span class="token string-interpolation string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic"># The predictions are a google.protobuf.Value representation of the model's predictions.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    predictions </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> response</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">predictions</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> prediction </span><span class="token keyword" style="color:#00009f">in</span><span class="token plain"> predictions</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        logging</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">info</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string" style="color:#e3116c">" prediction:"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token builtin">dict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">prediction</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><br></span></code></pre></div></div>
<p>Now you are ready to hit the endpoint and receive the prediction.</p>
<div class="language-python codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-python codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">instance </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"dayofweek"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">4</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"hourofday"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">13</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"pickup_longitude"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">73.99</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"pickup_latitude"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">40.758</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"dropoff_latitude"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">41.742</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token string" style="color:#e3116c">"dropoff_longitude"</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-</span><span class="token number" style="color:#36acaa">73.07</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">predict</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">PROJECT_ID</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> ENDPOINT</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> instance</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span></code></pre></div></div>
<p>You can refer to my repository for the complete code: <a href="https://github.com/p-s-vishnu/taxibooking-vertexai" target="_blank" rel="noopener noreferrer" class="">💻 Code</a>.</p>]]></content:encoded>
            <category>Use Case</category>
            <category>Machine Learning</category>
        </item>
        <item>
            <title><![CDATA[Common Product Metrics]]></title>
            <link>https://www.vishnups.com/blog/product-metrics</link>
            <guid>https://www.vishnups.com/blog/product-metrics</guid>
            <pubDate>Mon, 29 Nov 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Some of the common product metrics used in product management.]]></description>
            <content:encoded><![CDATA[<p>Some of the common product metrics used in product management.</p>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="1-user-engagement-metrics">1. <strong>User engagement metrics</strong><a href="https://www.vishnups.com/blog/product-metrics#1-user-engagement-metrics" class="hash-link" aria-label="Direct link to 1-user-engagement-metrics" title="Direct link to 1-user-engagement-metrics" translate="no">​</a></h3>
<ul>
<li class="">
<p>Number of sessions per user.</p>
</li>
<li class="">
<p>Sessions duration for a cohorts/group, over time</p>
</li>
<li class="">
<p>Number of key user actions per session. eg: number of likes, etc</p>
</li>
<li class="">
<p>CTR (Click-through rate)</p>
</li>
</ul>
<div class="language-math codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-math codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">(Number of click / Total Impressions) * 100</span><br></span></code></pre></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="2-business-metrics">2. <strong>Business metrics</strong><a href="https://www.vishnups.com/blog/product-metrics#2-business-metrics" class="hash-link" aria-label="Direct link to 2-business-metrics" title="Direct link to 2-business-metrics" translate="no">​</a></h3>
<ul>
<li class="">ROI: Return on Investment - <code>The value is in %</code></li>
</ul>
<div class="language-math codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-math codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">((Gain from investment - Cost of Investment) / Cost of Investment ) * 100</span><br></span></code></pre></div></div>
<ul>
<li class="">LTV/CLV: Customer Lifetime Value.</li>
</ul>
<p>Net profit you will generate until the customer churns or stops paying for service. Alternate metrics is Customer Lifetime Revenue, where one excludes the customer servicing cost (salary of employees, server cost, etc).</p>
<ul>
<li class="">CAC: Customer Acquisition Cost.</li>
</ul>
<p>It is the ratio of (Sales and marketing expense)/(number of new customers).</p>
<ul>
<li class="">
<p>ARPA: Average revenue per account</p>
</li>
<li class="">
<p>MRR: Monthly recurring revenue</p>
</li>
<li class="">
<p>Revenue churn rate</p>
</li>
</ul>
<p>Percentage of revenue loss per month due to churn or stoppage of service.</p>
<ul>
<li class="">Retention rate [not a good metric]</li>
</ul>
<p>Far less actionable than other metric like Churn metric</p>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="3-customer-service-metrics">3. <strong>Customer service metrics</strong><a href="https://www.vishnups.com/blog/product-metrics#3-customer-service-metrics" class="hash-link" aria-label="Direct link to 3-customer-service-metrics" title="Direct link to 3-customer-service-metrics" translate="no">​</a></h3>
<ul>
<li class="">
<p>Number of incoming support ticket</p>
</li>
<li class="">
<p>FCR: First Call Resolution</p>
</li>
<li class="">
<p>Net Promoter Score</p>
<div class="language-math codeBlockContainer_eYKS theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_SFq9"><pre tabindex="0" class="prism-code language-math codeBlock_go4x thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_iQjv"><span class="token-line" style="color:#393A34"><span class="token plain">Promoters % - Detractors %</span><br></span></code></pre></div></div>
<blockquote>
<p>Range: -100% to 100%</p>
</blockquote>
</li>
</ul>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="4-churn-analysis">4. <strong>Churn analysis</strong><a href="https://www.vishnups.com/blog/product-metrics#4-churn-analysis" class="hash-link" aria-label="Direct link to 4-churn-analysis" title="Direct link to 4-churn-analysis" translate="no">​</a></h3>
<div class="theme-admonition theme-admonition-tip admonition_iHmK alert alert--success"><div class="admonitionHeading_BWUg"><span class="admonitionIcon_Q0AD"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>Tips</div><div class="admonitionContent_gGp9"><p>For counts, take Medians over Means as they are less sensitive to outliers.</p><p>Churn analysis, do a t-test of the mean churned and retained users.</p></div></div>
<h3 class="anchor anchorTargetStickyNavbar_xRYd" id="references">References<a href="https://www.vishnups.com/blog/product-metrics#references" class="hash-link" aria-label="Direct link to References" title="Direct link to References" translate="no">​</a></h3>
<ol>
<li class="">
<p><a href="https://productcoalition.com/critical-metrics-every-product-manager-must-track-c5f1e46e3423" target="_blank" rel="noopener noreferrer" class="">Critical Metrics Every Product Manager Must Track</a></p>
</li>
<li class="">
<p><a href="http://www.nirandfar.com/2013/12/are-you-focusing-too-much-on-growth-how-to-measure-habits.html" target="_blank" rel="noopener noreferrer" class="">How to Measure Growth: Cohort Analysis and Retention Rate</a></p>
</li>
<li class="">
<p><a href="http://www.newnorth.com/how-to-calculate-metrics-for-customer-retention/" target="_blank" rel="noopener noreferrer" class="">Calculating Customer Retention (Fixed and Rolling)</a></p>
</li>
<li class="">
<p><a href="http://www.evergage.com/blog/how-calculate-customer-retention/" target="_blank" rel="noopener noreferrer" class="">How to Calculate Customer Retention and Dollar Retention</a></p>
</li>
<li class="">
<p><a href="http://www.vindicia.com/measuring-customer-retention-key-metrics-matter/" target="_blank" rel="noopener noreferrer" class="">Measuring Customer Retention: Retention and Average Lifetime Customer Value</a></p>
</li>
<li class="">
<p>[Source for WhatsApp Monthly Active Users]</p>
</li>
</ol>]]></content:encoded>
            <category>Use Case</category>
        </item>
        <item>
            <title><![CDATA[Booking.com's RS]]></title>
            <link>https://www.vishnups.com/blog/booking-com-rs</link>
            <guid>https://www.vishnups.com/blog/booking-com-rs</guid>
            <pubDate>Fri, 29 Oct 2021 00:00:00 GMT</pubDate>
            <description><![CDATA[Summary of Booking.com's RS, their Machine Learning Productionization System.]]></description>
            <content:encoded><![CDATA[<p>Summary of Booking.com's RS, their Machine Learning Productionization System.</p>
<p><img decoding="async" loading="lazy" alt="Booking.com RS" src="https://www.vishnups.com/assets/images/booking-rs-tradeoff-d0eabca64e0b42a26e3be193416aa8ac.png" width="1236" height="990" class="img_dCa6"></p>
<p>🛐 One of the Core ideas of booking.com: "Diversity gives us strength".</p>
<p>🥕 Requirements:</p>
<ol>
<li class=""><strong>Consistency:</strong> online predictions and offline should match</li>
<li class=""><strong>High availability:</strong> system available 24/7</li>
<li class=""><strong>Low latency:</strong> real-time or near real-time predictions</li>
<li class=""><strong>Scalability:</strong> Should be able to handle multiple requests simultaneously.</li>
<li class=""><strong>Observability:</strong> Monitor input and output space.</li>
<li class=""><strong>Reusability:</strong> The same model can be used in multiple places eg: a family-friendly hotel predictor can be used on the home page and in many filters.</li>
</ol>
<p>👨‍👨‍👦‍👦 The fantastic four approach</p>
<ol>
<li class="">
<p><strong>Lookup tables:</strong>
▴ Precompute all the possible input vectors and save them as key-value pairs.
For a prediction, they have to just look up. It is Low latency, horizontally scaleable - Implemented using the Cassandra key-value store (or in memory if they are small enough).
Disadvantages:
▴ Computation overhead and possibly resource wastage, even more, difficult with newer model versions.
Usage:
▴ Discrete input space cases, User / accommodation / destination identifiers.</p>
</li>
<li class="">
<p><strong>Generalized Linear Models (GLMs):</strong>
▴ The model representation is stored in the linear form of weight and bias and computed when needed. Can also be SVMs. So continuous input. - It doesn’t matter which training algorithm is used as long as it can be represented by a weight vector, an input transformation and link function, it can be run in production.
▴ Inner product &lt; vectorize(X), W&gt;
▴ Argsort for ranking the results based on the score
Disadvantage:
▴ An extra step, once trained convert to linear form.
Usage:
▴ User context models, destination, recommendations, etc</p>
</li>
<li class="">
<p><strong>Native libraries:</strong>
▴ Most straightforward approach: Train the model to serialize it and deserialize before serving.
Disadvantage
▴ It has latency issues, this is usually optimized for training and not necessarily for serving.
Usage:
▴ Tree-based model, GBT, NN</p>
</li>
<li class="">
<p><strong>Scripted models:</strong>
▴ A script is invoked during the request which gives the flexibility to control output for cases like post-processing.
▴ Flexibility for post-processing.
Disadvantage
▴ Each line of code will determine the online request lifecycle latency.
Usage
▴ For unsupported libraries and models with extra logic.</p>
</li>
</ol>
<p><strong>Reference:</strong> <a href="https://booking.ai/https-booking-ai-machine-learning-production-3ee8fe943c70" target="_blank" rel="noopener noreferrer" class="">Booking.com's RS</a></p>]]></content:encoded>
            <category>MLOps</category>
            <category>Machine Learning</category>
        </item>
    </channel>
</rss>