<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://debabrot.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://debabrot.github.io/" rel="alternate" type="text/html" /><updated>2026-06-09T11:18:47+00:00</updated><id>https://debabrot.github.io/feed.xml</id><title type="html">Debabrot’s blog</title><subtitle>Exploring the world of data, one byte at a time. This blog dives into data science, recommender systems, big data, Apache Spark, and emerging tech—offering insights, tutorials, and real-world applications for curious minds and tech enthusiasts.</subtitle><author><name>Debabrot bhuyan</name></author><entry><title type="html">Building a Product Enrichment Workflow with FastAPI and LangGraph</title><link href="https://debabrot.github.io/ai/python/langgraph/fastapi/product-enhancement-blog/" rel="alternate" type="text/html" title="Building a Product Enrichment Workflow with FastAPI and LangGraph" /><published>2026-06-08T00:00:00+00:00</published><updated>2026-06-08T00:00:00+00:00</updated><id>https://debabrot.github.io/ai/python/langgraph/fastapi/product-enhancement-blog</id><content type="html" xml:base="https://debabrot.github.io/ai/python/langgraph/fastapi/product-enhancement-blog/"><![CDATA[<h1 id="building-a-product-enrichment-workflow-with-fastapi-langgraph-and-streamlit">Building a Product Enrichment Workflow with FastAPI, LangGraph, and Streamlit</h1>

<p>Recently, I built a small proof-of-concept to explore agentic workflows using LangGraph.</p>

<p>The goal was simple: take partially complete product information, combine it with user-provided context, and use an LLM-powered workflow to generate enriched, structured product data.</p>

<p>Rather than building a monolithic prompt, I wanted to experiment with a multi-agent architecture and understand how orchestration frameworks like LangGraph fit into real applications.</p>

<h2 id="the-problem">The Problem</h2>

<p>Many product datasets contain incomplete information:</p>

<ul>
  <li>Missing descriptions</li>
  <li>Sparse specifications</li>
  <li>Inconsistent metadata</li>
  <li>Additional context scattered across documents</li>
</ul>

<p>This POC accepts a product, optional supporting context, and uploaded documents, then generates an enriched product profile using an AI workflow.</p>

<h2 id="architecture">Architecture</h2>

<p>The application consists of three main layers:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Streamlit Frontend
        │
        ▼
FastAPI Backend
        │
        ▼
LangGraph Workflow
        │
        ├── Retrieval Agent
        └── Enrichment Agent
        │
        ▼
Structured Product Output
</code></pre></div></div>

<h3 id="frontend">Frontend</h3>

<p>The Streamlit UI provides:</p>

<ul>
  <li>Product selection</li>
  <li>Context input</li>
  <li>Document upload support</li>
  <li>Enrichment results display</li>
</ul>

<h3 id="backend">Backend</h3>

<p>The FastAPI service exposes a single <code class="language-plaintext highlighter-rouge">/enrich</code> endpoint and keeps route handlers intentionally thin. Business logic lives inside service and workflow layers.</p>

<h3 id="agent-workflow">Agent Workflow</h3>

<p>The enrichment process is orchestrated using LangGraph:</p>

<ol>
  <li>Retrieve relevant context</li>
  <li>Aggregate user inputs</li>
  <li>Generate enriched product information</li>
  <li>Return structured output using Pydantic schemas</li>
</ol>

<p>This separation made it easier to reason about responsibilities and experiment with agent behavior.</p>

<h2 id="technology-choices">Technology Choices</h2>

<p>The project uses:</p>

<ul>
  <li>Python 3.11</li>
  <li>FastAPI</li>
  <li>Streamlit</li>
  <li>LangGraph</li>
  <li>LangChain</li>
  <li>Pydantic v2</li>
  <li>OpenRouter</li>
  <li>DeepSeek V4 Flash</li>
</ul>

<p>For observability, I also integrated OpenTelemetry tracing with Jaeger, which made it much easier to understand workflow execution and LLM interactions.</p>

<h2 id="what-i-learned">What I Learned</h2>

<p>A few takeaways from building this project:</p>

<ul>
  <li>LangGraph provides a clean way to model multi-step AI workflows.</li>
  <li>Keeping API handlers thin improves maintainability.</li>
  <li>Structured outputs with Pydantic significantly reduce parsing headaches.</li>
  <li>Tracing becomes extremely valuable once workflows involve multiple agents and LLM calls.</li>
  <li>For small POCs, simple architectures often beat over-engineered solutions.</li>
</ul>

<h2 id="current-limitations">Current Limitations</h2>

<p>This project intentionally remains lightweight and does not include:</p>

<ul>
  <li>Authentication</li>
  <li>Persistent storage</li>
  <li>Human-in-the-loop workflows</li>
  <li>Vector databases</li>
  <li>Batch processing</li>
  <li>Multi-user support</li>
</ul>

<p>The objective was to learn agent orchestration patterns rather than build a production-ready platform.</p>

<h2 id="whats-next">What’s Next</h2>

<p>Some areas I’d like to explore next:</p>

<ul>
  <li>Evaluation frameworks for enrichment quality</li>
  <li>Human-in-the-loop approval workflows</li>
  <li>Persistence and workflow state management</li>
  <li>Retrieval-augmented enrichment using vector databases</li>
</ul>

<p>Building this project was a useful exercise in combining modern Python APIs, agent orchestration, structured outputs, and observability into a single workflow.</p>

<p>The complete source code is available on GitHub.</p>]]></content><author><name>Debabrot bhuyan</name></author><category term="AI" /><category term="Python" /><category term="LangGraph" /><category term="FastAPI" /><category term="langgraph" /><category term="fastapi" /><category term="llm" /><category term="agents" /><summary type="html"><![CDATA[Building a Product Enrichment Workflow with FastAPI, LangGraph, and Streamlit]]></summary></entry><entry><title type="html">Your Database Schema Is the Real Architecture</title><link href="https://debabrot.github.io/reliability/microservices/system%20design/importance-of-schema-design/" rel="alternate" type="text/html" title="Your Database Schema Is the Real Architecture" /><published>2026-02-10T00:00:00+00:00</published><updated>2026-02-10T00:00:00+00:00</updated><id>https://debabrot.github.io/reliability/microservices/system%20design/importance-of-schema-design</id><content type="html" xml:base="https://debabrot.github.io/reliability/microservices/system%20design/importance-of-schema-design/"><![CDATA[<p>We obsess over algorithms, debate frameworks, and refactor business logic—yet treat our database schema as an afterthought. We create tables to “make it work,” postponing hard decisions until scale forces our hand.</p>

<p>That’s backwards.</p>

<p><strong>Your schema isn’t just storage—it’s the contract that defines performance, cost, and evolvability.</strong> A thoughtful design compounds value for years; a rushed one becomes technical debt no amount of application optimization can fully undo.</p>

<p>Here’s what that looks like in practice: designing the schema for a product similarity microservice serving real-time “customers also viewed” recommendations.</p>

<hr />

<h3 id="the-hidden-tradeoffs-in-every-schema-decision">The Hidden Tradeoffs in Every Schema Decision</h3>

<p>When designing a schema, you’re making explicit tradeoffs:</p>

<table>
  <thead>
    <tr>
      <th>Dimension</th>
      <th>What It Means</th>
      <th>Why It Matters</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Read Patterns</strong></td>
      <td>Point lookup, range scan, or joins?</td>
      <td>Dictates indexing and whether denormalization pays off</td>
    </tr>
    <tr>
      <td><strong>Write Frequency</strong></td>
      <td>Batch updates vs. real-time mutations</td>
      <td>Optimize for read speed or write concurrency</td>
    </tr>
    <tr>
      <td><strong>Latency Budget</strong></td>
      <td>P99 requirements for critical paths</td>
      <td>Joins add latency; denormalization adds storage</td>
    </tr>
    <tr>
      <td><strong>Cost Sensitivity</strong></td>
      <td>Storage vs. compute vs. I/O</td>
      <td>10% more storage might save 50% in query costs</td>
    </tr>
    <tr>
      <td><strong>Schema Evolution</strong></td>
      <td>How will fields change?</td>
      <td>Rigid schemas break deployments; flexible ones sacrifice queryability</td>
    </tr>
    <tr>
      <td><strong>Consistency Needs</strong></td>
      <td>Strong vs. eventual</td>
      <td>Can you shard freely or need transactional guarantees?</td>
    </tr>
  </tbody>
</table>

<p>These aren’t academic. They manifest as 3 a.m. pages when your recommendation API spikes to 800ms during Black Friday.</p>

<hr />

<h3 id="relational-vs-document-its-not-binary">Relational vs. Document: It’s Not Binary</h3>

<p>Modern workloads often demand <strong>hybrid approaches</strong>:</p>

<ul>
  <li><strong>Pure relational</strong> excels for dynamic relationship traversal but joins kill latency in high-throughput reads.</li>
  <li><strong>Pure document</strong> shines for self-contained aggregates but struggles with cross-document queries and referential integrity.</li>
</ul>

<p>The sweet spot? <strong>Use relational structure for identity and relationships; embed denormalized data where access patterns are predictable.</strong> You get SQL’s query power where you need flexibility and document-style reads where latency is non-negotiable.</p>

<hr />

<h3 id="case-study-product-similarity-schema">Case Study: Product Similarity Schema</h3>

<p>For our service—sub-100ms recommendations, &lt;100k products, weekly batch updates—we chose a hybrid PostgreSQL schema that deliberately denormalizes:</p>

<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">CREATE</span> <span class="k">TABLE</span> <span class="n">product_similarities</span> <span class="p">(</span>
    <span class="n">product_id</span> <span class="nb">VARCHAR</span><span class="p">(</span><span class="mi">50</span><span class="p">)</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
    <span class="n">recommendations</span> <span class="n">JSONB</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>  <span class="c1">-- Denormalized similarity list</span>
    <span class="n">created_at</span> <span class="n">TIMESTAMPTZ</span> <span class="k">DEFAULT</span> <span class="k">CURRENT_TIMESTAMP</span><span class="p">,</span>
    <span class="n">is_active</span> <span class="nb">BOOLEAN</span> <span class="k">DEFAULT</span> <span class="k">TRUE</span><span class="p">,</span>
    <span class="n">batch_id</span> <span class="nb">VARCHAR</span><span class="p">(</span><span class="mi">50</span><span class="p">)</span> <span class="k">NOT</span> <span class="k">NULL</span><span class="p">,</span>
    <span class="k">PRIMARY</span> <span class="k">KEY</span> <span class="p">(</span><span class="n">product_id</span><span class="p">,</span> <span class="n">created_at</span><span class="p">)</span>
<span class="p">);</span>
</code></pre></div></div>

<p><strong>Why this works:</strong></p>

<ul>
  <li>
    <p><strong>Single-row reads:</strong> Entire similarity list in one <code class="language-plaintext highlighter-rouge">JSONB</code> field. One index lookup (<code class="language-plaintext highlighter-rouge">product_id</code> + <code class="language-plaintext highlighter-rouge">is_active</code>)—no joins, no aggregation.</p>
  </li>
  <li>
    <p><strong>Versioned updates:</strong> Weekly batches insert new versions instead of overwriting. Old versions stay active until new batch loads—zero downtime, instant rollbacks.</p>
  </li>
  <li>
    <p><strong>Operational simplicity:</strong> PostgreSQL gives strong consistency and familiar tooling. No need for DynamoDB or Cassandra when writes are weekly and reads are point lookups.</p>
  </li>
  <li>
    <p><strong>Controlled flexibility:</strong> <code class="language-plaintext highlighter-rouge">JSONB</code> lets us index nested fields later (e.g., by <code class="language-plaintext highlighter-rouge">score</code>) without schema migrations today.</p>
  </li>
</ul>

<p>We accepted tradeoffs: higher storage from versioning and periodic cleanup needs. But these are manageable compared to unpredictable join latency or fragile batch updates.</p>

<hr />

<h3 id="the-takeaway">The Takeaway</h3>

<p>Schema design forces you to confront reality: <em>How will this actually be used?</em> It’s where data models meet production constraints—latency budgets, cost ceilings, inevitable change.</p>

<p>Don’t treat your schema as plumbing. Treat it as architecture. The hour spent modeling access patterns today saves weeks of firefighting tomorrow. When your API serves millions of requests per second, the database won’t lie about the decisions you made—or deferred—when no one was watching.</p>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Reliability" /><category term="Microservices" /><category term="System Design" /><category term="system-design" /><category term="schema-design" /><summary type="html"><![CDATA[We obsess over algorithms, debate frameworks, and refactor business logic—yet treat our database schema as an afterthought. We create tables to “make it work,” postponing hard decisions until scale forces our hand.]]></summary></entry><entry><title type="html">Making GenAI Systems More Reliable: Lessons from the Trenches</title><link href="https://debabrot.github.io/reliability/microservices/genai/rag/making-genai-system-reliable/" rel="alternate" type="text/html" title="Making GenAI Systems More Reliable: Lessons from the Trenches" /><published>2026-01-05T00:00:00+00:00</published><updated>2026-01-05T00:00:00+00:00</updated><id>https://debabrot.github.io/reliability/microservices/genai/rag/making-genai-system-reliable</id><content type="html" xml:base="https://debabrot.github.io/reliability/microservices/genai/rag/making-genai-system-reliable/"><![CDATA[<p>When you’re building production GenAI systems, <strong>reliability isn’t optional</strong>—it’s the line between a demo and a deployable product.</p>

<p>We learned this the hard way.</p>

<p>We had a GenAI-powered bot that returned structured JSON responses to a microservice. Even with <code class="language-plaintext highlighter-rouge">temperature=0</code>, <strong>about 10% of responses were malformed</strong>, triggering 4xx errors in our Grafana dashboards. We’d implemented retries, but they were costly—in latency, tokens, and unpredictability.</p>

<p>We couldn’t switch to a more capable (or expensive) model due to constraints. We tried prompt engineering, schema validation with Pydantic, and deterministic settings—but the LLM kept tripping over <strong>JSON formatting</strong>. The <em>content</em> was often correct, but a missing quote, an unescaped newline, or a trailing comma would break parsing.</p>

<p>So instead of fighting the model’s inherent non-determinism, we <strong>built a safety net</strong>.</p>

<p>We added a lightweight post-processing layer:</p>
<ul>
  <li>When Pydantic raised an <code class="language-plaintext highlighter-rouge">InvalidJSONError</code>,</li>
  <li>We applied a targeted regex-based cleanup to extract and restructure the JSON,</li>
  <li>Then re-validated the result.</li>
</ul>

<p><strong>The outcome? 4xx errors dropped from 10% to just 2%.</strong></p>

<h3 id="the-takeaway">The Takeaway</h3>

<blockquote>
  <p><strong>Reliability in GenAI systems isn’t about eliminating randomness—it’s about containing it.</strong></p>
</blockquote>

<p>You can’t always control what the LLM outputs, but you <em>can</em> design resilient wrappers around its known failure modes. Sometimes, the most “unsexy” code—regex, fallback parsers, strict validation—is what makes your AI system <strong>production-ready</strong>.</p>

<p>If you’re shipping GenAI, ask yourself:<br />
<em>Where is your system brittle? And what’s your Plan B when the LLM inevitably glitches?</em></p>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Reliability" /><category term="Microservices" /><category term="Genai" /><category term="RAG" /><category term="genai" /><category term="llm" /><category term="ai-engineering" /><category term="prompt-engineering" /><summary type="html"><![CDATA[When you’re building production GenAI systems, reliability isn’t optional—it’s the line between a demo and a deployable product.]]></summary></entry><entry><title type="html">Building a Privacy-First RAG Microservice with FastAPI &amp;amp; Open Source Tools</title><link href="https://debabrot.github.io/backend/microservices/genai/rag/building-rag-microservice/" rel="alternate" type="text/html" title="Building a Privacy-First RAG Microservice with FastAPI &amp;amp; Open Source Tools" /><published>2025-09-21T00:00:00+00:00</published><updated>2025-09-21T00:00:00+00:00</updated><id>https://debabrot.github.io/backend/microservices/genai/rag/building-rag-microservice</id><content type="html" xml:base="https://debabrot.github.io/backend/microservices/genai/rag/building-rag-microservice/"><![CDATA[<blockquote>
  <p>“I didn’t want to just <em>use</em> AI — I wanted to <em>understand</em> it.”</p>
</blockquote>

<p>That’s why I built my own <strong>RAG (Retrieval-Augmented Generation) microservice</strong> from scratch using <strong>FastAPI</strong> and entirely <strong>open-source tools</strong> — no Bedrock, no OpenAI API, no managed services. Just raw, hands-on learning.</p>

<p>This project was born out of curiosity and a desire to peel back the layers of modern LLM-powered applications. I wanted to know: <em>What’s really happening under the hood?</em> And more importantly — <em>how can I keep my data private while still leveraging powerful models?</em></p>

<hr />

<h2 id="-the-tech-stack">🧰 The Tech Stack</h2>

<p>Here’s what I wired together:</p>

<ul>
  <li><strong>MinIO</strong> → Self-hosted S3-compatible storage for document uploads</li>
  <li><strong>Chroma</strong> → Lightweight, open-source vector database for storing embeddings</li>
  <li><strong>vLLM</strong> → High-throughput LLM inference engine (for future chat integration)</li>
  <li><strong>Hugging Face Text Embeddings Inference</strong> → Fast, scalable embedding generation</li>
  <li><strong>FastAPI</strong> → The glue holding it all together with clean, async endpoints</li>
</ul>

<p>All containerized via Docker and orchestrated with <code class="language-plaintext highlighter-rouge">docker-compose.yml</code> — because if it’s not reproducible, did it even happen?</p>

<hr />

<h2 id="-endpoints-i-built">🚀 Endpoints I Built</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>POST   /upload      → Upload file → stores <span class="k">in </span>MinIO
DELETE /delete/<span class="o">{</span>filename<span class="o">}</span> → Delete file from MinIO
POST   /embed       → Generate embeddings <span class="k">for </span>ALL files <span class="k">in </span>MinIO
POST   /embed/<span class="o">{</span>filename<span class="o">}</span> → Embed a specific file
POST   /retrieve    → Retrieve top-k relevant chunks <span class="k">for </span>a query
</code></pre></div></div>

<p>Simple? Yes.<br />
Powerful? Absolutely.</p>

<p>Each endpoint is designed to be modular, testable, and — most importantly — <em>understandable</em>. No black boxes.</p>

<hr />

<h2 id="-what-i-learned-the-hard-way">🧠 What I Learned (The Hard Way)</h2>

<p>Building RAG from scratch revealed surprising complexities:</p>

<h3 id="1-file-embedding-synchronization">1. File-Embedding Synchronization</h3>

<p>What happens when you rename or delete a file? Do you delete its embeddings? How do you track which embeddings belong to which file version? I learned the hard way that <strong>random hashes don’t cut it</strong> — you need <strong>deterministic hashing</strong> (e.g., based on filename + content hash) to maintain consistency.</p>

<h3 id="2-the-need-for-an-embedding-registry">2. The Need for an Embedding Registry</h3>

<p>I didn’t realize how crucial it is to maintain a <strong>metadata registry</strong> mapping files → embedding IDs → chunk IDs. Without it, you’re flying blind when files change or models get updated.</p>

<h3 id="3-pipeline-rebuilds-are-inevitable">3. Pipeline Rebuilds Are Inevitable</h3>

<p>Switching embedding models? Updating chunking strategies? You need a <strong>full re-embedding pipeline</strong> — with evaluation metrics to measure drift or performance loss. RAG isn’t “set and forget.” It’s a living system.</p>

<hr />

<h2 id="-why-privacy-matters-and-why-i-built-this">🔐 Why Privacy Matters (And Why I Built This)</h2>

<p>Let’s be honest: <strong>most LLM services keep your data</strong>. Whether it’s for training, telemetry, or “improving the product,” your documents, queries, and context are rarely truly private.</p>

<p>I built this so I — and you — can:</p>

<p>✅ Use local files<br />
✅ Avoid sending data to third parties<br />
✅ Swap models freely (Llama, Mistral, Phi, etc.)<br />
✅ Own the entire stack — from ingestion to response</p>

<p>This isn’t just a toy project. It’s a <strong>blueprint for private, auditable, enterprise-ready RAG</strong>.</p>

<hr />

<h2 id="️-whats-next">🗺️ What’s Next?</h2>

<p>I’m now integrating <strong>vLLM for chat endpoints</strong> — letting users query their documents and get LLM-generated responses — all locally.</p>

<p>Future plans:</p>

<ul>
  <li>Experiment with <strong>different RAG architectures</strong> (HyDE, sub-queries, re-ranking)</li>
  <li>Add <strong>evaluation metrics</strong> (hit rate, MRR, faithfulness)</li>
  <li>Support <strong>multiple file types</strong> (PDF, DOCX, PPTX, images via OCR)</li>
  <li>Build a <strong>simple frontend</strong> (maybe with Streamlit or React)</li>
</ul>

<hr />

<h2 id="-sneak-peek-project-structure">📁 Sneak Peek: Project Structure</h2>

<p>For the curious (and fellow nerds), here’s how I organized the codebase:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>.
├── Dockerfile
├── docker-compose.yml
├── backend/
│   └── app/
│       ├── routers/          # FastAPI route handlers
│       ├── services/         # Business logic
│       │   ├── embeddings/   # Document loading, chunking, embedding, vector storage
│       │   └── llm/          # Future LLM integration
│       ├── schemas/          # Pydantic models
│       ├── domain/           # Protocols
│       ├── core/             # Config
│       └── utils/            # Helpers (logging, ID generation)
└── uploads/                  # Local file storage (mounted to MinIO)
</code></pre></div></div>

<p>Clean separation of concerns. Testable components. Extensible design.</p>

<hr />

<h2 id="-final-thoughts">💬 Final Thoughts</h2>

<p>This project taught me more than any tutorial or course ever could. There’s something deeply satisfying about wiring together open-source tools, debugging tokenizer mismatches, and finally seeing your RAG system return a relevant chunk from your own document.</p>

<p>If you’re thinking about dipping your toes into RAG — <strong>don’t reach for an API first</strong>. Build it yourself. Break it. Fix it. You’ll learn 10x more.</p>

<hr />

<p>🔗 <strong>GitHub Repo</strong>: <a href="https://github.com/debabrot/intelligent-doc-assistant">github.com/debabrot/intelligent-doc-assistant</a></p>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Backend" /><category term="Microservices" /><category term="Genai" /><category term="RAG" /><category term="fastapi" /><category term="llm" /><category term="chroma" /><category term="vllm" /><category term="minio" /><category term="huggingface" /><category term="privacy" /><summary type="html"><![CDATA[“I didn’t want to just use AI — I wanted to understand it.”]]></summary></entry><entry><title type="html">You Can’t Fix What You Can’t See: Why Monitoring Is the Dashboard of Your Software</title><link href="https://debabrot.github.io/backend/microservices/telemetry/importance-of-monitoring/" rel="alternate" type="text/html" title="You Can’t Fix What You Can’t See: Why Monitoring Is the Dashboard of Your Software" /><published>2025-08-31T00:00:00+00:00</published><updated>2025-08-31T00:00:00+00:00</updated><id>https://debabrot.github.io/backend/microservices/telemetry/importance-of-monitoring</id><content type="html" xml:base="https://debabrot.github.io/backend/microservices/telemetry/importance-of-monitoring/"><![CDATA[<p>Imagine driving a car with no speedometer, no fuel gauge, and no warning lights.</p>

<p>You’d have no idea how fast you’re going. You wouldn’t know if the engine was overheating. You might run out of gas — and only realize it when the car sputters to a halt on the highway.</p>

<p>Now ask yourself:<br />
<strong>Would you trust this car for a long journey?</strong></p>

<p>Probably not.</p>

<p>Yet, every day, thousands of software systems run in production <strong>without any real-time visibility</strong>. No metrics. No alerts. No dashboard.<br />
And when something goes wrong, teams scramble in the dark — reacting to angry users instead of preventing issues.</p>

<p>This is where <strong>monitoring</strong> comes in.<br />
It’s not flashy. It won’t win design awards.<br />
But it’s the <strong>dashboard of your software</strong> — and without it, you’re flying blind.</p>

<hr />

<h2 id="1-your-system-needs-a-dashboard--just-like-your-car">1. Your System Needs a Dashboard — Just Like Your Car</h2>

<p>Think about what your car’s dashboard tells you:</p>

<ul>
  <li><strong>Speed</strong>: Am I going too fast or too slow?</li>
  <li><strong>Fuel level</strong>: How much longer can I go?</li>
  <li><strong>Engine temperature</strong>: Is something overheating?</li>
  <li><strong>Warning lights</strong>: Is the brake system failing?</li>
</ul>

<p>These aren’t just nice-to-have — they’re essential for safe, confident driving.</p>

<p>Now translate that to your software:</p>

<table>
  <thead>
    <tr>
      <th>Car Dashboard</th>
      <th>Software Monitoring</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Speed</td>
      <td>Request rate (traffic)</td>
    </tr>
    <tr>
      <td>Fuel level</td>
      <td>Server resource usage</td>
    </tr>
    <tr>
      <td>Engine temperature</td>
      <td>Latency or error rate</td>
    </tr>
    <tr>
      <td>Check Engine light</td>
      <td>Alert on failure</td>
    </tr>
  </tbody>
</table>

<p>Without monitoring, you won’t know your API is slow until customers complain.<br />
You won’t notice a memory leak until your app crashes.<br />
You’re not just driving blind — you’re letting your users be the canaries in the coal mine.</p>

<blockquote>
  <p><strong>Monitoring doesn’t prevent failures. But it ensures you’re never surprised by them.</strong></p>
</blockquote>

<hr />

<h2 id="2-why-monitoring-matters--in-any-system">2. Why Monitoring Matters — In Any System</h2>

<p>You might think monitoring is only for massive platforms like Netflix or Amazon.</p>

<p>But the truth is:<br />
<strong>Every system in production needs monitoring — even small apps.</strong></p>

<p>Here’s why:</p>

<ul>
  <li><strong>Problems happen silently.</strong> A background job fails? A database connection times out? Without metrics, you won’t know.</li>
  <li><strong>Performance degrades slowly.</strong> That API endpoint that used to respond in 100ms now takes 800ms — over weeks. Only monitoring catches that drift.</li>
  <li><strong>You can’t improve what you can’t measure.</strong> Want to optimize performance? Scale your infrastructure? You need data.</li>
</ul>

<p>Monitoring turns guesswork into insight.<br />
It transforms <em>“I think it’s slow”</em> into <em>“Error rate increased by 40% at 2:15 PM.”</em></p>

<p>And that changes everything.</p>

<hr />

<h2 id="3-meet-prometheus-your-softwares-dashboard-tool">3. Meet Prometheus: Your Software’s Dashboard Tool</h2>

<p>So how do you build this dashboard?</p>

<p>One of the best tools for the job is <strong>Prometheus</strong> — a powerful, open-source monitoring system used by companies of all sizes.</p>

<p>Here’s what makes it great:</p>

<ul>
  <li>📊 <strong>It collects metrics over time</strong> — like request counts, response times, or memory usage.</li>
  <li>
    <p>🔍 <strong>It lets you query with PromQL</strong> — a simple but powerful language to ask things like:</p>

    <pre><code class="language-promql">rate(http_requests_total[5m])
</code></pre>

    <p>(That shows how many HTTP requests your app is handling per second.)</p>
  </li>
  <li>📈 <strong>It works with almost anything</strong> — web apps, APIs, databases, servers, even batch jobs.</li>
  <li>💡 <strong>It’s free, lightweight, and easy to start with</strong> — no enterprise license required.</li>
</ul>

<p>You don’t need Kubernetes or microservices to use Prometheus.<br />
Even a simple Flask or Express app can expose metrics in minutes.</p>

<hr />

<h2 id="4-what-to-monitor-the-vital-signs-of-your-app">4. What to Monitor: The Vital Signs of Your App</h2>

<p>You don’t need to track everything. Start with the <strong>four vital signs</strong> of any system:</p>

<h3 id="1-traffic">1. <strong>Traffic</strong></h3>

<p>How many requests are hitting your app?<br />
A sudden drop might mean a deployment broke your API. A spike could mean a DDoS or a viral feature.</p>

<h3 id="2-errors">2. <strong>Errors</strong></h3>

<p>What percentage of requests are failing?<br />
Even 1% error rate can mean hundreds of frustrated users.</p>

<h3 id="3-latency">3. <strong>Latency</strong></h3>

<p>How fast are responses?<br />
Users notice delays over 300ms. Monitoring helps you catch slowdowns early.</p>

<h3 id="4-saturation">4. <strong>Saturation</strong></h3>

<p>Is your server running out of CPU, memory, or disk?<br />
This is your “fuel gauge” — it tells you when you’re running on empty.</p>

<p>Track these four, and you’ll catch 90% of issues before they become outages.</p>

<hr />

<h2 id="5-from-data-to-action-alerts-and-dashboards">5. From Data to Action: Alerts and Dashboards</h2>

<p>Raw numbers aren’t enough. You need <strong>visibility</strong> and <strong>action</strong>.</p>

<p>That’s where tools like <strong>Grafana</strong> come in.</p>

<p>With Grafana, you can turn Prometheus data into beautiful, real-time dashboards — your software’s dashboard, just like in a car.</p>

<p>You can see:</p>

<ul>
  <li>Live request rates.</li>
  <li>Error trends over time.</li>
  <li>CPU and memory usage across servers.</li>
</ul>

<p>And with <strong>Alertmanager</strong> (part of the Prometheus ecosystem), you can set up alerts like:</p>

<blockquote>
  <p>“Notify me if error rate exceeds 1% for 5 minutes.”</p>
</blockquote>

<p>Now, instead of waking up to a Slack message saying “The site is down,” you get a quiet alert at 2:03 AM — and fix the issue before anyone notices.</p>

<hr />

<h2 id="start-small-but-start-now">Start Small, But Start Now</h2>

<p>You don’t need a perfect monitoring setup on day one.</p>

<p>Just start:</p>

<ol>
  <li>Add the Prometheus client library to your app (takes 10 minutes).</li>
  <li>Expose one metric (e.g., HTTP request count).</li>
  <li>Set up Prometheus to scrape it.</li>
  <li>Build one dashboard in Grafana.</li>
  <li>Create one alert.</li>
</ol>

<p>That’s it.</p>

<p>Over time, you’ll add more metrics, refine alerts, and gain deep insight into your system.</p>

<p>But the hardest step is the first one.</p>

<p>So ask yourself again:<br />
<strong>Are you driving blind? Or do you have a dashboard?</strong></p>

<p>Your software deserves to be seen.</p>

<p>Give it the visibility it needs — before the next outage catches you by surprise.</p>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Backend" /><category term="Microservices" /><category term="Telemetry" /><category term="Prometheus" /><category term="Monitoring" /><category term="Telemetry" /><summary type="html"><![CDATA[Imagine driving a car with no speedometer, no fuel gauge, and no warning lights.]]></summary></entry><entry><title type="html">TaskFlow: A Secure Task Manager Microservice</title><link href="https://debabrot.github.io/backend/microservices/taskflow-a-microservice-task-manager/" rel="alternate" type="text/html" title="TaskFlow: A Secure Task Manager Microservice" /><published>2025-08-10T00:00:00+00:00</published><updated>2025-08-10T00:00:00+00:00</updated><id>https://debabrot.github.io/backend/microservices/taskflow-a-microservice-task-manager</id><content type="html" xml:base="https://debabrot.github.io/backend/microservices/taskflow-a-microservice-task-manager/"><![CDATA[<blockquote>
  <p><em>“Ever wanted to build your own secure task manager from scratch? Meet <strong>TaskFlow</strong> — a lightweight, JWT-secured microservice that helps users manage tasks with confidence.”</em></p>
</blockquote>

<hr />

<h2 id="-what-is-taskflow">🔐 What Is TaskFlow?</h2>

<p><strong>TaskFlow</strong> is a secure, containerized microservice that lets users:</p>

<p>✅ Register &amp; log in<br />
✅ Create, view, edit, and delete personal tasks<br />
✅ Stay authenticated with JWT tokens<br />
✅ Run everything locally with one command</p>

<p>It’s built with:</p>

<ul>
  <li><strong>FastAPI</strong> (backend)</li>
  <li><strong>PostgreSQL</strong> (database)</li>
  <li><strong>Streamlit</strong> (frontend)</li>
  <li><strong>Docker &amp; Makefile</strong> (dev experience)</li>
  <li><strong>JWT + Argon2</strong> (security)</li>
</ul>

<p>And yes — it’s <strong>fully functional</strong>, tested, and ready to run.</p>

<p>But more than that — it’s a <strong>learning scaffold</strong> for concepts I once found intimidating:</p>

<ul>
  <li>How do APIs actually work?</li>
  <li>What’s the difference between Pydantic schemas and SQLAlchemy models?</li>
  <li>How do you securely store passwords?</li>
  <li>What does “microservice” even mean in practice?</li>
</ul>

<p>Spoiler: I now understand all of it — and you can too.</p>

<hr />

<h2 id="-see-it-in-action">🎥 See It in Action</h2>

<p>Here’s how TaskFlow works — in just a few seconds:</p>

<h3 id="1--user-registration">1. 🔹 User Registration</h3>

<p>New users can sign up with a valid email and strong password.</p>

<p><img src="/assets/images/taskflow/register_user.gif" alt="Register" /></p>

<h3 id="2--login--authentication">2. 🔹 Login &amp; Authentication</h3>

<p>Users log in and receive a secure <strong>JWT access token</strong>. No sessions, no cookies — just stateless, verifiable tokens.</p>

<p><img src="/assets/images/taskflow/login.gif" alt="Login" /></p>

<h3 id="3--create--manage-tasks">3. 🔹 Create &amp; Manage Tasks</h3>

<p>Once logged in, users can create, view, and manage their tasks in a clean, responsive Streamlit UI.</p>

<p><img src="/assets/images/taskflow/create_tasks.gif" alt="Tasks" /></p>

<blockquote>
  <p><em>Note: These GIFs are part of the project repo — feel free to explore the real thing!</em></p>
</blockquote>

<hr />

<h2 id="-why-this-matters">💡 Why This Matters</h2>

<p>You might think: <em>“Another task app? Really?”</em></p>

<p>But here’s the truth: <strong>CRUD + Authentication</strong> is the foundation of 90% of web apps.</p>

<p>Whether you’re building a note-taking app, a CRM, or a SaaS platform — you’ll need:</p>

<ul>
  <li>User management</li>
  <li>Data persistence</li>
  <li>Secure access control</li>
  <li>API design</li>
</ul>

<p>TaskFlow gives you all of that — in a <strong>simple, understandable, and extendable</strong> way.</p>

<p>And because it’s containerized with <strong>Docker and Makefile</strong>, you can spin it up in seconds — no dependency hell, no “it works on my machine” excuses.</p>

<hr />

<h2 id="️-try-it-yourself-its-easy">🛠️ Try It Yourself (It’s Easy!)</h2>

<p>Want to run TaskFlow locally? Here’s all it takes:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/debabrot/TaskFlow
<span class="nb">cd </span>TaskFlow

<span class="c"># Build and start backend (PostgreSQL + FastAPI)</span>
make up-build

<span class="c"># In another terminal, launch the frontend</span>
<span class="c"># Create virtual environment (optional but recommended)</span>
python <span class="nt">-m</span> venv .venv
<span class="nb">source</span> .venv/bin/activate

<span class="c"># Install Streamlit</span>
pip <span class="nb">install </span>streamlit

<span class="c"># Launch the frontend</span>
streamlit run frontend/app/main.py
</code></pre></div></div>

<p>That’s it.</p>

<p>You’ll have:</p>

<ul>
  <li>FastAPI running on <code class="language-plaintext highlighter-rouge">http://localhost:8000</code> (with live docs at <code class="language-plaintext highlighter-rouge">/docs</code>)</li>
  <li>PostgreSQL database managed via Docker</li>
  <li>Streamlit frontend on <code class="language-plaintext highlighter-rouge">http://localhost:8501</code></li>
</ul>

<p>👉 <strong>GitHub Repo</strong>: <a href="https://github.com/debabrot/TaskFlow">github.com/debabrot/TaskFlow</a></p>

<hr />

<h2 id="-whats-next">🔮 What’s Next?</h2>

<p>TaskFlow was just the beginning. Now that I’ve mastered the fundamentals, I’m extending it with:</p>

<ul>
  <li><strong>Multi-tenancy</strong> – So teams or organizations can have isolated workspaces</li>
  <li><strong>Role-Based Access Control (RBAC)</strong> – Admin, editor, viewer roles</li>
  <li><strong>HMAC request signing</strong> – For enhanced API security</li>
  <li><strong>Better frontend</strong> – Maybe React, or keep Streamlit for prototyping?</li>
</ul>

<p>This project proved something powerful:<br />
<strong>You don’t need to be a backend expert to build like one.</strong><br />
You just need curiosity, a clear goal, and the willingness to break things — and fix them.</p>

<hr />

<h2 id="-final-thought">🌱 Final Thought</h2>

<blockquote>
  <p><em>“Building TaskFlow wasn’t just about managing tasks — it was about mastering the fundamentals of modern backend development.”</em></p>
</blockquote>

<hr />

<p>If you’re coming from a <strong>data science or analytics background</strong>, you probably know Python well — for pandas, scikit-learn, maybe even Streamlit dashboards.</p>

<p>But when I first saw <strong>Pydantic models</strong> like this:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">UserCreate</span><span class="p">(</span><span class="n">BaseModel</span><span class="p">):</span>
    <span class="n">email</span><span class="p">:</span> <span class="n">EmailStr</span>
    <span class="n">password</span><span class="p">:</span> <span class="nb">str</span>
</code></pre></div></div>

<p>…I blinked. Twice.</p>

<p>“What is this <em>alien syntax</em>?” I thought. “Since when did Python get types?”</p>

<p>That moment sparked a journey — one that led me to dive deep into <strong>microservices, APIs, authentication, databases, and security</strong>. And the result? <strong>TaskFlow</strong>: a full-stack, production-style task management microservice built with <strong>FastAPI, PostgreSQL, JWT, and Streamlit</strong>.</p>

<p>This wasn’t just a side project. It was my <strong>crash course in modern backend development</strong> — and I’m excited to share it with you.</p>

<p>From Pydantic confusion to JWT clarity, from ORM uncertainty to SQLAlchemy confidence — this project transformed how I see software.</p>

<p>If you’re a data scientist, analyst, or junior dev looking to level up your full-stack skills, <strong>start small. Build something real. Break it. Fix it. Repeat.</strong></p>

<p>And who knows? Your next side project might just teach you more than any tutorial ever could.</p>

<hr />

<p>💬 <strong>Thoughts? Questions? Want to contribute or suggest features?</strong><br />
Let’s chat on GitHub or LinkedIn!<br />
Star the repo if you found it helpful:<br />
⭐ <a href="https://github.com/debabrot/TaskFlow">github.com/debabrot/TaskFlow</a></p>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Backend" /><category term="Microservices" /><category term="Python" /><category term="FastAPI" /><category term="Microservices" /><category term="PostgreSQL" /><category term="JWT" /><category term="TaskManager" /><summary type="html"><![CDATA[“Ever wanted to build your own secure task manager from scratch? Meet TaskFlow — a lightweight, JWT-secured microservice that helps users manage tasks with confidence.”]]></summary></entry><entry><title type="html">Infrastructure as code</title><link href="https://debabrot.github.io/chatbots/aws%20lex/infrastructure-as-code/" rel="alternate" type="text/html" title="Infrastructure as code" /><published>2025-08-04T00:00:00+00:00</published><updated>2025-08-04T00:00:00+00:00</updated><id>https://debabrot.github.io/chatbots/aws%20lex/infrastructure-as-code</id><content type="html" xml:base="https://debabrot.github.io/chatbots/aws%20lex/infrastructure-as-code/"><![CDATA[<h1 id="infrastructure-as-code-with-aws-cdk-automating-the-mood-based-music-recommender">Infrastructure as Code with AWS CDK: Automating the Mood-Based Music Recommender</h1>

<p>In the journey to build a <strong>Mood-Based Music Recommender</strong> chatbot, we’ve explored the frontend (React + Vite), the conversational engine (AWS Lex), and the serverless backend (FastAPI on Lambda with Mangum). Now, it’s time to talk about the invisible glue that holds it all together — <strong>Infrastructure as Code (IaC)</strong> using <strong>AWS Cloud Development Kit (CDK)</strong>.</p>

<p>If you’ve been manually clicking through the AWS Console to deploy S3 buckets, Lambda functions, or API Gateways, this post will change how you think about infrastructure — forever.</p>

<hr />

<h2 id="1-️-what-is-infrastructure-as-code-iac">1. 🛠️ What is Infrastructure as Code (IaC)?</h2>

<p><strong>Infrastructure as Code (IaC)</strong> is the practice of managing and provisioning infrastructure — servers, databases, networks, APIs — using code instead of manual processes.</p>

<p>Instead of navigating the AWS Console to:</p>

<ul>
  <li>Create an S3 bucket</li>
  <li>Upload a Lambda function</li>
  <li>Set up API Gateway</li>
  <li>Configure IAM roles</li>
</ul>

<p>You write <strong>declarative code</strong> that defines your entire stack. Then, with a single command, you deploy it — consistently, reliably, and repeatedly.</p>

<blockquote>
  <p>💡 Think of IaC like a blueprint for your cloud architecture. Just as you wouldn’t build a house without a plan, you shouldn’t deploy cloud apps without IaC.</p>
</blockquote>

<h3 id="why-iac-matters">Why IaC Matters?</h3>

<ul>
  <li><strong>Reproducibility:</strong> Deploy identical environments (dev, staging, prod) every time.</li>
  <li><strong>Version Control:</strong> Track infrastructure changes like code — with Git.</li>
  <li><strong>Faster Deployments:</strong> Automate setup in minutes, not hours.</li>
  <li><strong>Reduced Human Error:</strong> No more “I forgot to attach that policy” moments.</li>
  <li><strong>Team Collaboration:</strong> Share, review, and test infrastructure changes via pull requests.</li>
</ul>

<hr />

<h2 id="2--why-aws-cdk">2. 🚀 Why AWS CDK?</h2>

<p>There are several IaC tools available — <strong>Terraform</strong>, <strong>CloudFormation</strong>, <strong>Serverless Framework</strong> — but for this project, I used <strong>AWS CDK</strong>.</p>

<h3 id="what-is-aws-cdk">What is AWS CDK?</h3>

<p>The <strong>AWS Cloud Development Kit (CDK)</strong> is an open-source framework that lets you define cloud resources using familiar programming languages like <strong>Python</strong>, <strong>TypeScript</strong>, <strong>Java</strong>, or <strong>C#</strong>.</p>

<p>Unlike raw CloudFormation JSON/YAML templates, CDK uses <strong>high-level constructs</strong> that abstract away boilerplate, letting you focus on your application.</p>

<blockquote>
  <p>✅ You write Python → CDK generates CloudFormation → AWS deploys your stack.</p>
</blockquote>

<h3 id="why-aws-cdk-was-chosen-this-project">Why AWS CDK was chosen This Project?</h3>

<table>
  <thead>
    <tr>
      <th>Reason</th>
      <th>Explanation</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Python Support</strong></td>
      <td>no need to learn YAML or TypeScript.</td>
    </tr>
    <tr>
      <td><strong>High-Level Constructs</strong></td>
      <td>Pre-built components (like <code class="language-plaintext highlighter-rouge">Bucket</code>, <code class="language-plaintext highlighter-rouge">Function</code>, <code class="language-plaintext highlighter-rouge">Api</code>) reduce errors.</td>
    </tr>
    <tr>
      <td><strong>Tight AWS Integration</strong></td>
      <td>Native support for all AWS services — including Lex, Lambda, S3, and API Gateway.</td>
    </tr>
    <tr>
      <td><strong>Extensible</strong></td>
      <td>Create reusable components (e.g., <code class="language-plaintext highlighter-rouge">LexBotStack</code>, <code class="language-plaintext highlighter-rouge">ApiStack</code>) for future projects.</td>
    </tr>
    <tr>
      <td><strong>Perfect for Serverless</strong></td>
      <td>Ideal for Lambda-heavy, event-driven architecture.</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="3--how-i-used-cdk-in-the-mood-based-music-recommender">3. 🧱 How I used CDK in the Mood-Based Music Recommender</h2>

<p>The entire architecture — from the React frontend to the Lex bot and backend API — is defined and deployed using AWS CDK in Python.</p>

<p>Here’s a breakdown of what CDK manages:</p>

<h3 id="-components-provisioned-via-cdk">✅ Components Provisioned via CDK</h3>

<table>
  <thead>
    <tr>
      <th>Component</th>
      <th>CDK Construct Used</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>React Frontend Hosting</strong></td>
      <td><code class="language-plaintext highlighter-rouge">Bucket</code> + <code class="language-plaintext highlighter-rouge">CloudFrontWebDistribution</code></td>
    </tr>
    <tr>
      <td><strong>FastAPI Backend (Lambda)</strong></td>
      <td><code class="language-plaintext highlighter-rouge">Function</code> + <code class="language-plaintext highlighter-rouge">LambdaRestApi</code></td>
    </tr>
    <tr>
      <td><strong>Lex Bot &amp; Intent</strong></td>
      <td>Custom CDK constructs using <code class="language-plaintext highlighter-rouge">CfnBot</code>, <code class="language-plaintext highlighter-rouge">CfnIntent</code>, etc.</td>
    </tr>
    <tr>
      <td><strong>Fulfillment Lambda</strong></td>
      <td><code class="language-plaintext highlighter-rouge">Function</code> with IAM permissions</td>
    </tr>
    <tr>
      <td><strong>API Gateway</strong></td>
      <td>Automatically created via <code class="language-plaintext highlighter-rouge">LambdaRestApi</code></td>
    </tr>
    <tr>
      <td><strong>IAM Roles &amp; Policies</strong></td>
      <td>Defined inline with resource creation</td>
    </tr>
    <tr>
      <td><strong>Environment Variables &amp; Permissions</strong></td>
      <td>Safely configured in code</td>
    </tr>
  </tbody>
</table>

<p>This means:<br />
➡️ One <code class="language-plaintext highlighter-rouge">cdk deploy</code> command = full stack up and running.<br />
➡️ One <code class="language-plaintext highlighter-rouge">cdk destroy</code> = clean teardown, no orphaned resources.</p>

<hr />

<h2 id="4--benefits-of-using-cdk-in-this-project">4. 🌱 Benefits of Using CDK in This Project</h2>

<table>
  <thead>
    <tr>
      <th>Benefit</th>
      <th>Impact</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Repeatable Deployments</strong></td>
      <td>Spin up dev/test environments in minutes.</td>
    </tr>
    <tr>
      <td><strong>Version-Controlled Infrastructure</strong></td>
      <td>All changes tracked in GitHub</td>
    </tr>
    <tr>
      <td><strong>CI/CD Integration</strong></td>
      <td>Trigger deployments on Git push using GitHub Actions.</td>
    </tr>
    <tr>
      <td><strong>Cost Management</strong></td>
      <td>Easily destroy unused stacks to avoid surprise bills.</td>
    </tr>
    <tr>
      <td><strong>Documentation</strong></td>
      <td>The code <em>is</em> the documentation — no outdated diagrams.</td>
    </tr>
  </tbody>
</table>

<hr />

<h2 id="5--challenges--how-to-overcame-them">5. 🛑 Challenges &amp; How to Overcame Them</h2>

<h3 id="️-learning-curve">⚠️ Learning Curve</h3>

<p>CDK requires understanding both AWS services and programming concepts.<br />
✅ <strong>Solution:</strong> Start small — deploy a single Lambda, then expand.</p>

<h3 id="️-lex-support-in-cdk">⚠️ Lex Support in CDK</h3>

<p>Lex V2 constructs are not fully high-level in CDK (yet).<br />
✅ <strong>Solution:</strong> Use <code class="language-plaintext highlighter-rouge">Cfn*</code> (CloudFormation) constructs with well-documented templates.</p>

<h3 id="️-local-testing">⚠️ Local Testing</h3>

<p>You can’t simulate Lex or API Gateway locally.<br />
✅ <strong>Solution:</strong> Use <code class="language-plaintext highlighter-rouge">cdk synth</code> to preview CloudFormation and test in a sandbox AWS account.</p>

<hr />

<h2 id="6--conclusion-why-iac-is-non-negotiable">6. 🎯 Conclusion: Why IaC is Non-Negotiable</h2>

<p>Building a serverless chatbot is powerful — but doing it manually is unsustainable.</p>

<p>By using <strong>AWS CDK</strong>, the entire <strong>Mood-Based Music Recommender</strong> has been turned into a repeatable, version-controlled, and scalable system. Whether you’re deploying for the first time or rolling out updates, CDK ensures consistency, reduces risk, and accelerates development.</p>

<blockquote>
  <p>🔥 Infrastructure isn’t just “set and forget.” With IaC, it’s <strong>code, collaboration, and control</strong>.</p>
</blockquote>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Chatbots" /><category term="AWS Lex" /><category term="AWS Lex" /><category term="CDK" /><category term="Chatbot" /><summary type="html"><![CDATA[Infrastructure as Code with AWS CDK: Automating the Mood-Based Music Recommender]]></summary></entry><entry><title type="html">FastAPI Lambda Backend with Mangum</title><link href="https://debabrot.github.io/chatbots/aws%20lex/fastapi-lambda-backend-with-mangum/" rel="alternate" type="text/html" title="FastAPI Lambda Backend with Mangum" /><published>2025-07-24T00:00:00+00:00</published><updated>2025-07-24T00:00:00+00:00</updated><id>https://debabrot.github.io/chatbots/aws%20lex/fastapi-lambda-backend-with-mangum</id><content type="html" xml:base="https://debabrot.github.io/chatbots/aws%20lex/fastapi-lambda-backend-with-mangum/"><![CDATA[<h1 id="-building-a-fastapi-lambda-backend-with-mangum">🚀 Building a FastAPI Lambda Backend with Mangum</h1>

<p>In our mood-based music recommender journey, we’ve explored AWS Lex and the overall architecture. Now, let’s dive into the backend—an efficient API powered by <strong>FastAPI</strong>, deployed on <strong>AWS Lambda</strong>, and made serverless-compatible with <strong>Mangum</strong>.</p>

<hr />

<h2 id="1-️-what-is-aws-lambda">1. ⚙️ What is AWS Lambda?</h2>

<p><strong>AWS Lambda</strong> is a serverless, event-driven compute service that runs code in response to events—without provisioning servers.</p>

<h3 id="-key-benefits">✅ Key Benefits:</h3>

<ul>
  <li><strong>Serverless:</strong> No infrastructure to manage.</li>
  <li><strong>Event-Driven:</strong> Triggered via API Gateway, S3, SQS, etc.</li>
  <li><strong>Pay-per-use:</strong> Billed per invocation and execution time.</li>
  <li><strong>Scalable:</strong> Automatically handles traffic spikes.</li>
  <li><strong>Multi-language support:</strong> Python, Node.js, Java, Go, and more.</li>
</ul>

<h3 id="-in-our-project">📌 In Our Project:</h3>

<ul>
  <li><strong>Lex Fulfillment:</strong> Handle chatbot logic.</li>
  <li><strong>API Backend:</strong> Serve React frontend, orchestrate services.</li>
</ul>

<hr />

<h2 id="2--creating-an-api-in-lambda-raw-vs-framework">2. 🌐 Creating an API in Lambda (Raw vs Framework)</h2>

<p>You can write raw Lambda functions for API Gateway, but it quickly becomes complex.</p>

<h3 id="-basic-lambda-api">🧱 Basic Lambda API:</h3>

<p>Handles <code class="language-plaintext highlighter-rouge">event</code> and returns a response dict.</p>

<h3 id="️-drawbacks-of-raw-lambda">⚠️ Drawbacks of Raw Lambda:</h3>

<ul>
  <li>Manual parsing/validation</li>
  <li>Difficult to scale with routes</li>
  <li>Error-prone for large apps</li>
</ul>

<p>Using a <strong>framework</strong> like FastAPI improves developer experience and code structure.</p>

<hr />

<h2 id="3--why-fastapi--mangum">3. 🧠 Why FastAPI + Mangum?</h2>

<h3 id="-fastapi-highlights">🚀 FastAPI Highlights:</h3>

<ul>
  <li><strong>Async Support:</strong> Great for I/O-heavy tasks.</li>
  <li><strong>Type-based Validation:</strong> Via Pydantic.</li>
  <li><strong>Auto Docs:</strong> Swagger &amp; ReDoc built-in.</li>
  <li><strong>Performance:</strong> Among the fastest Python frameworks.</li>
  <li><strong>Developer-Friendly:</strong> Intuitive syntax, great tooling.</li>
</ul>

<h3 id="-what-is-mangum">🔌 What is Mangum?</h3>

<p>AWS Lambda doesn’t run ASGI apps directly. <strong>Mangum</strong> bridges this gap:</p>

<ul>
  <li>Converts <strong>API Gateway events → ASGI scope</strong></li>
  <li>Converts <strong>ASGI responses → API Gateway format</strong></li>
  <li>Lets FastAPI run seamlessly on Lambda</li>
</ul>

<h3 id="-synergy-of-fastapi--mangum">⚡ Synergy of FastAPI + Mangum:</h3>

<ul>
  <li>Build modern APIs using familiar tools</li>
  <li>Enjoy Lambda’s scalability and cost-efficiency</li>
  <li>Avoid raw Lambda boilerplate</li>
</ul>

<hr />

<h2 id="4--pros---cons-of-fastapi--mangum-on-lambda">4. ✅ Pros &amp; ❌ Cons of FastAPI + Mangum on Lambda</h2>

<h3 id="-pros">✅ Pros:</h3>

<ol>
  <li>High performance (FastAPI + Lambda improvements)</li>
  <li>Easy development &amp; built-in validation</li>
  <li>Auto-scaling from zero</li>
  <li>Cost-effective for low/variable traffic</li>
  <li>No server maintenance</li>
  <li>Rich AWS integration</li>
  <li>Standard, maintainable code</li>
</ol>

<h3 id="-cons">❌ Cons:</h3>

<ol>
  <li><strong>Cold starts</strong> (though improving)</li>
  <li><strong>Package size</strong> can bloat deployment</li>
  <li><strong>Local testing</strong> can be tricky (use SAM or Serverless Framework)</li>
  <li><strong>Vendor lock-in</strong> with AWS deployment</li>
  <li><strong>Debugging</strong> is CloudWatch-heavy; needs tracing tools</li>
</ol>

<hr />

<h2 id="-conclusion">🧩 Conclusion</h2>

<p>FastAPI + Mangum + Lambda offers a modern, serverless API stack—perfect for our chatbot’s backend. It connects Lex and the React frontend with business logic that powers personalized music recommendations.</p>

<blockquote>
  <p>🛠️ In the next post, we’ll walk through <strong>inrastructure as a code using AWS CDK</strong>!</p>
</blockquote>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Chatbots" /><category term="AWS Lex" /><category term="AWS Lex" /><category term="CDK" /><category term="Chatbot" /><summary type="html"><![CDATA[🚀 Building a FastAPI Lambda Backend with Mangum]]></summary></entry><entry><title type="html">Building the lex bot</title><link href="https://debabrot.github.io/chatbots/aws%20lex/building-the-lex-bot/" rel="alternate" type="text/html" title="Building the lex bot" /><published>2025-07-16T00:00:00+00:00</published><updated>2025-07-16T00:00:00+00:00</updated><id>https://debabrot.github.io/chatbots/aws%20lex/building-the-lex-bot</id><content type="html" xml:base="https://debabrot.github.io/chatbots/aws%20lex/building-the-lex-bot/"><![CDATA[<h2 id="-building-the-lex-bot-for-mood-based-music-recommendation">🎤 Building the Lex Bot for Mood-Based Music Recommendation</h2>

<p>In this post, I will cover the core of the bot—<strong>building the Lex bot itself</strong>. I will define intents, create slots, configure prompts, and route the conversation using Lambda for fulfillment. I will also touch on slot validation and custom routing logic.</p>

<hr />

<h2 id="-recap-what-the-bot-does">🧠 Recap: What the Bot Does</h2>

<p>The chatbot helps users discover music recommendations based on their <strong>current mood</strong>. For example:</p>

<blockquote>
  <p><em>“I’m feeling energetic.”</em><br />
<em>“Suggest something chill.”</em><br />
<em>“I’m a bit down today.”</em></p>
</blockquote>

<p>Based on this input, the bot suggests genres or playlists aligned with that mood.</p>

<hr />

<h2 id="️-step-1-create-the-lex-bot">🛠️ Step 1: Create the Lex Bot</h2>

<ol>
  <li><strong>Go to AWS Console → Amazon Lex</strong></li>
  <li>Click <strong>“Create bot”</strong></li>
  <li>Choose <strong>Lex V2</strong></li>
  <li>
    <p>Fill in basic details:</p>

    <ul>
      <li><strong>Bot name:</strong> <code class="language-plaintext highlighter-rouge">MoodMusicBot</code></li>
      <li><strong>Language:</strong> English (US)</li>
      <li><strong>IAM permissions:</strong> Create a new role or use an existing one with Lex permissions</li>
      <li>Enable <strong>Children’s Privacy (COPPA)</strong> as per your need (probably “No”)</li>
      <li>Hit <strong>“Next”</strong></li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="️-step-2-define-the-intent">🗣️ Step 2: Define the Intent</h2>

<p>We only need one primary intent: <code class="language-plaintext highlighter-rouge">GetMusicRecommendationIntent</code></p>

<ol>
  <li>Create an intent and name it.</li>
  <li>
    <p>Add sample utterances:</p>

    <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I'm feeling {mood}
Suggest something {mood}
I want {mood} music
Music for when I'm {mood}
</code></pre></div>    </div>
  </li>
  <li>
    <p>Add a <strong>slot</strong> named <code class="language-plaintext highlighter-rouge">mood</code>:</p>

    <ul>
      <li>Slot type: Custom slot or use Amazon’s built-in <code class="language-plaintext highlighter-rouge">AMAZON.Literal</code></li>
      <li>Prompt: <em>“How are you feeling today?”</em></li>
      <li>Required: ✅</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="-step-3-slot-validation-optional-but-recommended">🧪 Step 3: Slot Validation (Optional but Recommended)</h2>

<p>A Lambda function can be used to validate the <code class="language-plaintext highlighter-rouge">mood</code> slot.</p>

<p>💡 Example: Only accept moods from a predefined list (<code class="language-plaintext highlighter-rouge">happy</code>, <code class="language-plaintext highlighter-rouge">sad</code>, <code class="language-plaintext highlighter-rouge">energetic</code>, <code class="language-plaintext highlighter-rouge">relaxed</code>, etc.)</p>

<p>Inside Lambda:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">validate_mood</span><span class="p">(</span><span class="n">mood</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
    <span class="n">valid_moods</span> <span class="o">=</span> <span class="p">[</span><span class="s">"happy"</span><span class="p">,</span> <span class="s">"sad"</span><span class="p">,</span> <span class="s">"relaxed"</span><span class="p">,</span> <span class="s">"energetic"</span><span class="p">,</span> <span class="s">"angry"</span><span class="p">]</span>
    <span class="k">return</span> <span class="n">mood</span><span class="p">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">in</span> <span class="n">valid_moods</span>
</code></pre></div></div>

<p>Then, return a <code class="language-plaintext highlighter-rouge">dialogAction</code> response to re-ask the question if the slot is invalid.</p>

<hr />

<h2 id="-step-4-add-fulfillment-lambda">🔄 Step 4: Add Fulfillment Lambda</h2>

<p>To integrate custom logic like returning different genres based on mood, add a Lambda function:</p>

<ol>
  <li>In the Lex intent, scroll to <strong>Fulfillment</strong></li>
  <li>Choose <strong>“AWS Lambda function”</strong></li>
  <li>Select or create a function</li>
</ol>

<p>Example response handler in Lambda:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">lambda_handler</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
    <span class="n">mood</span> <span class="o">=</span> <span class="n">event</span><span class="p">[</span><span class="s">'sessionState'</span><span class="p">][</span><span class="s">'intent'</span><span class="p">][</span><span class="s">'slots'</span><span class="p">][</span><span class="s">'mood'</span><span class="p">][</span><span class="s">'value'</span><span class="p">][</span><span class="s">'interpretedValue'</span><span class="p">]</span>
    
    <span class="n">music_map</span> <span class="o">=</span> <span class="p">{</span>
        <span class="s">"happy"</span><span class="p">:</span> <span class="s">"Pop or Dance"</span><span class="p">,</span>
        <span class="s">"sad"</span><span class="p">:</span> <span class="s">"Lo-fi or Acoustic"</span><span class="p">,</span>
        <span class="s">"relaxed"</span><span class="p">:</span> <span class="s">"Jazz or Chillhop"</span><span class="p">,</span>
        <span class="s">"energetic"</span><span class="p">:</span> <span class="s">"Rock or EDM"</span><span class="p">,</span>
        <span class="s">"angry"</span><span class="p">:</span> <span class="s">"Heavy Metal or Rap"</span>
    <span class="p">}</span>
    
    <span class="n">genre</span> <span class="o">=</span> <span class="n">music_map</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="n">mood</span><span class="p">.</span><span class="n">lower</span><span class="p">(),</span> <span class="s">"something interesting"</span><span class="p">)</span>
    
    <span class="k">return</span> <span class="p">{</span>
        <span class="s">"sessionState"</span><span class="p">:</span> <span class="p">{</span>
            <span class="s">"dialogAction"</span><span class="p">:</span> <span class="p">{</span>
                <span class="s">"type"</span><span class="p">:</span> <span class="s">"Close"</span>
            <span class="p">},</span>
            <span class="s">"intent"</span><span class="p">:</span> <span class="p">{</span>
                <span class="s">"name"</span><span class="p">:</span> <span class="n">event</span><span class="p">[</span><span class="s">'sessionState'</span><span class="p">][</span><span class="s">'intent'</span><span class="p">][</span><span class="s">'name'</span><span class="p">],</span>
                <span class="s">"state"</span><span class="p">:</span> <span class="s">"Fulfilled"</span>
            <span class="p">}</span>
        <span class="p">},</span>
        <span class="s">"messages"</span><span class="p">:</span> <span class="p">[{</span>
            <span class="s">"contentType"</span><span class="p">:</span> <span class="s">"PlainText"</span><span class="p">,</span>
            <span class="s">"content"</span><span class="p">:</span> <span class="sa">f</span><span class="s">"Based on your mood, I recommend listening to </span><span class="si">{</span><span class="n">genre</span><span class="si">}</span><span class="s"> music!"</span>
        <span class="p">}]</span>
    <span class="p">}</span>
</code></pre></div></div>

<h2 id="-test-the-bot">🧪 Test the Bot</h2>

<ol>
  <li>Build and deploy the bot</li>
  <li>Test utterances in the Lex console</li>
  <li>Try incorrect moods to see if validation kicks in</li>
  <li>
    <p>Try phrases like:</p>

    <ul>
      <li>“I want something chill”</li>
      <li>“Suggest music for when I’m angry”</li>
      <li>“Play music”</li>
    </ul>
  </li>
</ol>

<hr />

<h2 id="-bonus-custom-routing-logic-advanced">🔁 Bonus: Custom Routing Logic (Advanced)</h2>

<p>Let’s say in the future you add more intents like <code class="language-plaintext highlighter-rouge">GetPlaylist</code>, <code class="language-plaintext highlighter-rouge">SuggestArtist</code>, or handle fallback queries using Bedrock.</p>

<p>You can route to different logic branches in the Lambda function like:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">intent</span> <span class="o">=</span> <span class="n">event</span><span class="p">[</span><span class="s">'sessionState'</span><span class="p">][</span><span class="s">'intent'</span><span class="p">][</span><span class="s">'name'</span><span class="p">]</span>

<span class="k">if</span> <span class="n">intent</span> <span class="o">==</span> <span class="s">"GetMusicRecommendationIntent"</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">handle_music_recommendation</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">intent</span> <span class="o">==</span> <span class="s">"FallbackIntent"</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">route_to_bedrock_llm</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
</code></pre></div></div>

<hr />

<h2 id="-bonus-custom-workflow-using-code-hooks-advanced">🧩 Bonus: Custom Workflow Using Code Hooks (Advanced)</h2>

<p>By default, Lex handles the entire dialog flow—from prompting for slots to fulfillment—using its built-in dialog manager.</p>

<p>However, if you want <strong>full control over the conversation flow</strong>, you can <strong>enable code hooks</strong> and define custom workflows entirely in your Lambda function.</p>

<h3 id="-what-are-code-hooks">🔧 What Are Code Hooks?</h3>

<ul>
  <li>
    <p><strong>Code hooks</strong> let you intercept the flow at two points:</p>

    <ul>
      <li><strong>Dialog code hook</strong> (for slot elicitation, validation, branching)</li>
      <li><strong>Fulfillment code hook</strong> (for final action/response)</li>
    </ul>
  </li>
</ul>

<h3 id="-example-use-case-custom-routing">💡 Example Use Case: Custom Routing</h3>

<p>Let’s say you want to:</p>

<ul>
  <li>Skip some slots conditionally</li>
  <li>Add logic like: “If mood is <em>angry</em> and it’s after 10 PM, suggest <em>calm</em> music”</li>
  <li>Or forward fallback requests to an LLM (e.g., Claude or Bedrock)</li>
</ul>

<p>Enable the code hook in your Lex console:</p>

<ol>
  <li>Go to your intent</li>
  <li>Under <strong>“Lambda code hooks”</strong></li>
  <li>Enable <strong>“Dialog code hook”</strong> and/or <strong>“Fulfillment code hook”</strong></li>
</ol>

<p>Your Lambda function now controls the routing logic:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">lambda_handler</span><span class="p">(</span><span class="n">event</span><span class="p">,</span> <span class="n">context</span><span class="p">):</span>
    <span class="n">invocation_source</span> <span class="o">=</span> <span class="n">event</span><span class="p">[</span><span class="s">'invocationSource'</span><span class="p">]</span>
    
    <span class="k">if</span> <span class="n">invocation_source</span> <span class="o">==</span> <span class="s">"DialogCodeHook"</span><span class="p">:</span>
        <span class="c1"># Perform validation, conditional logic, etc.
</span>        <span class="k">return</span> <span class="n">handle_dialog_code_hook</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
    
    <span class="k">elif</span> <span class="n">invocation_source</span> <span class="o">==</span> <span class="s">"FulfillmentCodeHook"</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">handle_fulfillment</span><span class="p">(</span><span class="n">event</span><span class="p">)</span>
</code></pre></div></div>

<p>This gives you <strong>complete flexibility</strong> to customize how the bot behaves, beyond what Lex’s native configuration allows.</p>

<hr />

<h2 id="-lex-bots-vs-llm-bots-when-to-use-what">🧠 Lex Bots vs LLM Bots: When to Use What?</h2>

<p>You might wonder—why use Lex at all when we now have powerful LLMs?</p>

<p>Here’s a quick comparison:</p>

<table>
  <thead>
    <tr>
      <th>Feature</th>
      <th>Lex Bot</th>
      <th>LLM-based Bot</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Cost</strong></td>
      <td>Predictable, lower per-interaction cost</td>
      <td>Higher cost per call (tokens + inference)</td>
    </tr>
    <tr>
      <td><strong>Latency</strong></td>
      <td>Low latency (near-instant response)</td>
      <td>Can have higher latency</td>
    </tr>
    <tr>
      <td><strong>Control</strong></td>
      <td>Deterministic, rule-based flow</td>
      <td>Open-ended, flexible answers</td>
    </tr>
    <tr>
      <td><strong>Use Cases</strong></td>
      <td>FAQs, routing, form-filling, IVRs</td>
      <td>Complex queries, fallback answers, summaries</td>
    </tr>
    <tr>
      <td><strong>Maintenance</strong></td>
      <td>Easy to manage with UI/console</td>
      <td>Requires prompt tuning, monitoring</td>
    </tr>
  </tbody>
</table>

<h3 id="-tldr">🔹 TL;DR:</h3>

<blockquote>
  <p>Use <strong>Lex</strong> for structured workflows. Use <strong>LLMs</strong> when you need open-ended understanding or fallback handling. A hybrid approach is often the best.</p>
</blockquote>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Chatbots" /><category term="AWS Lex" /><category term="AWS Lex" /><category term="CDK" /><category term="Chatbot" /><summary type="html"><![CDATA[🎤 Building the Lex Bot for Mood-Based Music Recommendation]]></summary></entry><entry><title type="html">Project Architecture Overview</title><link href="https://debabrot.github.io/chatbots/aws%20lex/project-architecture-overview/" rel="alternate" type="text/html" title="Project Architecture Overview" /><published>2025-07-06T00:00:00+00:00</published><updated>2025-07-06T00:00:00+00:00</updated><id>https://debabrot.github.io/chatbots/aws%20lex/project-architecture-overview</id><content type="html" xml:base="https://debabrot.github.io/chatbots/aws%20lex/project-architecture-overview/"><![CDATA[<h2 id="project-architecture-overview">Project Architecture Overview</h2>

<p>Before diving into individual components, let’s take a step back and look at the overall architecture powering the <strong>Mood-Based Music Recommender</strong> chatbot.</p>

<p>This project uses a <strong>modular, serverless architecture</strong> built on AWS, with a clear separation between the UI, conversational engine, and fulfillment logic. It showcases how to build scalable, event-driven applications using modern cloud-native tools.</p>

<h2 id="-architecture-diagram">🔧 Architecture Diagram</h2>
<p><img src="/assets/images/mood_based_music_recommender/architecture.png" alt="Architecture Diagram" /></p>

<h3 id="-high-level-overview">🧩 High-Level Overview</h3>

<p>Here’s how the system is structured:</p>

<ol>
  <li>
    <p><strong>Frontend (React + Vite)</strong></p>

    <ul>
      <li>A responsive single-page application built with React and Vite.</li>
      <li>Hosted on <strong>Amazon S3</strong> and served via <strong>CloudFront</strong> for global availability and fast performance.</li>
      <li>The frontend presents the chatbot UI and interacts with the backend API to communicate with the Lex bot.</li>
    </ul>
  </li>
  <li>
    <p><strong>Backend API (FastAPI + Lambda)</strong></p>

    <ul>
      <li>A <strong>FastAPI</strong> application wrapped using <strong>Mangum</strong>, deployed as an <strong>AWS Lambda</strong> function.</li>
      <li>This API acts as the middle layer between the frontend and AWS Lex.</li>
      <li>When a user sends a message, the API uses <strong><code class="language-plaintext highlighter-rouge">boto3</code></strong> to invoke the Lex bot and retrieve a response. This approach allows custom logging, validation, and integration hooks around Lex interactions.</li>
    </ul>
  </li>
  <li>
    <p><strong>Conversational Engine (AWS Lex V2)</strong></p>

    <ul>
      <li>The core chatbot is built with <strong>AWS Lex V2</strong>.</li>
      <li>It handles natural language understanding — detecting intents (like requesting a song) and extracting relevant slot values (e.g., user mood).</li>
      <li>The Lex bot is intentionally kept simple with a single intent and slot for focused, effective interactions.</li>
    </ul>
  </li>
  <li>
    <p><strong>Fulfillment Logic (AWS Lambda)</strong></p>

    <ul>
      <li>Once Lex recognizes the intent and slot, it triggers a <strong>fulfillment Lambda function</strong>.</li>
      <li>This function processes the user mood and returns a song recommendation.</li>
      <li>In the future, this logic can be extended to include dynamic sources like music APIs or personalized recommendations.</li>
    </ul>
  </li>
  <li>
    <p><strong>Infrastructure as Code (AWS CDK)</strong></p>

    <ul>
      <li>The entire infrastructure — including Lex bot, Lambda functions, API Gateway, S3 bucket, and CloudFront — is provisioned using <strong>AWS CDK</strong> in Python.</li>
      <li>This enables repeatable deployments and version-controlled infrastructure changes.</li>
    </ul>
  </li>
  <li>
    <p><strong>Version Control (GitHub)</strong></p>

    <ul>
      <li>All code and infrastructure definitions are maintained in GitHub, making collaboration and CI/CD integration easier.</li>
    </ul>
  </li>
</ol>

<h3 id="-request-flow">🔄 Request Flow</h3>

<p>Here’s how a typical request flows through the system:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>User → React Frontend → FastAPI (Lambda) → AWS Lex (via boto3) → Fulfillment Lambda → Response → Frontend UI
</code></pre></div></div>

<p>This design ensures:</p>

<ul>
  <li>Full control over the Lex interaction lifecycle via the API.</li>
  <li>Clean separation between the frontend and business logic.</li>
  <li>Serverless scalability and low cost for low-to-medium traffic workloads.</li>
</ul>

<hr />]]></content><author><name>Debabrot bhuyan</name></author><category term="Chatbots" /><category term="AWS Lex" /><category term="AWS Lex" /><category term="CDK" /><category term="Chatbot" /><summary type="html"><![CDATA[Project Architecture Overview]]></summary></entry></feed>