<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adnan Siddiqi</title>
    <description>The latest articles on DEV Community by Adnan Siddiqi (@kadnan).</description>
    <link>https://dev.to/kadnan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F130384%2Fc2868d79-08cb-432d-b9ed-1c43345fe86b.jpeg</url>
      <title>DEV Community: Adnan Siddiqi</title>
      <link>https://dev.to/kadnan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kadnan"/>
    <language>en</language>
    <item>
      <title>Reimagining Customer Support with GenAI</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Wed, 29 Oct 2025 11:58:23 +0000</pubDate>
      <link>https://dev.to/kadnan/reimagining-customer-support-with-genai-54o8</link>
      <guid>https://dev.to/kadnan/reimagining-customer-support-with-genai-54o8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm7iefxyi4u2kq9ea0bi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmm7iefxyi4u2kq9ea0bi.png" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’ve ever worked in customer support, you know the feeling.&lt;/p&gt;

&lt;p&gt;It’s 2 PM on a Wednesday. Your inbox is overflowing. A customer just sent their third “following up” email. Your manager wants to know why last week’s tickets are still open. And somewhere in the back of your mind, you’re wondering: &lt;em&gt;Why does this feel so hard?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here’s the thing: Most support teams aren’t failing because people aren’t trying hard enough. They’re struggling because the systems we’ve built over years of “making do” were never designed to handle today’s volume, complexity, or customer expectations.&lt;/p&gt;

&lt;p&gt;And the stakes? They’ve never been higher. According to Zendesk Benchmark data, &lt;strong&gt;&lt;em&gt;more than half of consumers will switch to a competitor after just one bad experience.&lt;/em&gt;&lt;/strong&gt; Not three strikes. &lt;em&gt;One&lt;/em&gt;. Even more concerning? Research from Coveo shows that &lt;strong&gt;&lt;em&gt;56% won’t even tell you they’re unhappy&lt;/em&gt;&lt;/strong&gt;. They’ll just quietly leave.&lt;/p&gt;

&lt;p&gt;At the company where I work, customers would often blame our support teams for delays, but the reality was more complicated. Sometimes it was us. Sometimes it was waiting on the customer. Sometimes it was dependencies on other teams. But without clear evidence, these conversations turned into “he said, she said” situations that damaged trust on both sides.&lt;/p&gt;

&lt;p&gt;So I built a tool that generates &lt;strong&gt;&lt;em&gt;complete reports explaining exactly why each ticket got delayed.&lt;/em&gt;&lt;/strong&gt; It scans through ticket histories, internal notes, response times, and handoffs to create an objective timeline. No more finger-pointing. Just facts.&lt;/p&gt;

&lt;p&gt;The impact was immediate. Our teams could defend themselves when delays weren’t their fault, and more importantly, we could identify and fix the real bottlenecks when they &lt;em&gt;were&lt;/em&gt; on us.&lt;/p&gt;

&lt;p&gt;But here’s what surprised me: that one tool opened my eyes to a much bigger opportunity. If AI could bring this level of clarity to delays, what else could it do? I started researching, and what I found was a complete transformation waiting to happen across customer support.&lt;/p&gt;

&lt;p&gt;This series is everything I’ve learned about where GenAI can actually make a difference (not just the chatbot hype you’ve heard a thousand times).&lt;/p&gt;

&lt;p&gt;Let’s start with the problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Real Pain Points (And Why They Matter)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Repetitive Queries
&lt;/h4&gt;

&lt;p&gt;You’ve seen it a hundred times: “Where’s my order?” “How do I reset my password?” “Can I get a refund?”&lt;/p&gt;

&lt;p&gt;These questions make up 40–60% of your ticket volume. Your agents could answer them in their sleep, and honestly, that’s part of the problem. When half your day is spent copy-pasting the same responses, burnout isn’t far behind.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; Smart, intent-aware chatbots can handle these queries automatically by training on your actual support conversations, not generic templates. Your team gets their time back for the problems that actually need a human touch.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Delayed Resolutions
&lt;/h4&gt;

&lt;p&gt;Ever watched an agent hunt through three different systems, two Slack channels, and an outdated wiki just to find an answer? Or worse, wait two days for engineering to respond before they can even help the customer?&lt;/p&gt;

&lt;p&gt;These delays aren’t anyone’s fault. They’re just the reality of working with fragmented information and cross-team dependencies. But here’s what customers experience: waiting. And waiting erodes trust faster than almost anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; AI can scan ticket histories, internal notes, and past conversations in seconds. It can tell you &lt;em&gt;why&lt;/em&gt; a ticket got delayed (like “waiting on engineering response, average lag: 42 hours”) so you can fix the bottleneck, not just the symptom.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(This was my starting point, and once I saw how powerful this transparency was for both our teams and our customers, I couldn’t unsee all the other places AI could help.)&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Inconsistent Tone &amp;amp; Quality
&lt;/h4&gt;

&lt;p&gt;Some agents are naturally warm and empathetic. Others are efficient but might come across as cold. Some overexplain. Others are too brief.&lt;/p&gt;

&lt;p&gt;It’s not that anyone’s doing it wrong. Everyone just has their own style. But when customers interact with your brand, they expect consistency. And when 73% of consumers will switch to a competitor after multiple bad experiences (Zendesk), every interaction counts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; Real-time coaching that gently nudges agents: &lt;em&gt;“This might sound a bit defensive. Try acknowledging their frustration first.”&lt;/em&gt; It’s like having an editor looking over your shoulder, one that helps you sound like your best self.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Poor Root Cause Visibility
&lt;/h4&gt;

&lt;p&gt;Ask most support managers what’s causing delays, and you’ll get hunches. “Engineering handoffs take forever.” “The knowledge base is outdated.” “We’re understaffed.”&lt;/p&gt;

&lt;p&gt;But without data, it’s hard to know where to focus or to make the case for change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; AI can analyze thousands of tickets and surface patterns: &lt;em&gt;“40% of this month’s delays were caused by missing API documentation.”&lt;/em&gt; Suddenly, you’re not guessing anymore. You’re making decisions based on what’s actually happening.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. Knowledge Fragmentation
&lt;/h4&gt;

&lt;p&gt;The answer exists &lt;em&gt;somewhere&lt;/em&gt;. Maybe it’s in a Slack thread from six months ago. Maybe someone wrote it in Notion. Maybe it’s just living in one senior agent’s brain.&lt;/p&gt;

&lt;p&gt;This isn’t sustainable, and when that person leaves, the knowledge walks out with them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; AI-powered knowledge hubs can pull information from everywhere (Slack, docs, past tickets) and surface it exactly when agents need it. Even better? When AI spots a gap (like 15 tickets about the same issue with no help article), it can draft one automatically.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. Customer Frustration
&lt;/h4&gt;

&lt;p&gt;Long wait times. Generic responses. Being transferred three times. We’ve all been on the receiving end of bad support, and we know how quickly it erodes trust.&lt;/p&gt;

&lt;p&gt;Your agents aren’t trying to frustrate customers. But when they’re drowning in volume, quality suffers. And remember: most unhappy customers won’t complain. They’ll just leave. Silently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; Sentiment analysis can detect when a customer’s frustration is escalating (even if they’re being polite) and flag the ticket for immediate attention. Catch the problem early, and you can turn a potential detractor into a loyal advocate.&lt;/p&gt;

&lt;h4&gt;
  
  
  7. Agent Training Overload
&lt;/h4&gt;

&lt;p&gt;New hires are eager to help. But learning your product, your tools, your processes? That takes weeks, sometimes months.&lt;/p&gt;

&lt;p&gt;Meanwhile, they’re hesitant to ask “dumb questions,” so they either guess or escalate everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; An AI mentor that new agents can ask anything: &lt;em&gt;“How do I process a refund for a canceled subscription?”&lt;/em&gt; Instant, accurate answers without bothering their overwhelmed teammates.&lt;/p&gt;

&lt;h4&gt;
  
  
  8. The SLA Panic Cycle
&lt;/h4&gt;

&lt;p&gt;Most teams only notice a problem when a ticket is about to breach its SLA. Then it’s all hands on deck, scrambling to close it before the deadline.&lt;/p&gt;

&lt;p&gt;This reactive approach is exhausting, and it doesn’t actually improve the customer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; Predictive AI can flag tickets that are &lt;em&gt;likely&lt;/em&gt; to breach within the first 15 minutes. You get ahead of the problem instead of constantly playing catch-up.&lt;/p&gt;

&lt;h4&gt;
  
  
  9. Hidden Patterns in Delays
&lt;/h4&gt;

&lt;p&gt;Sometimes tickets take longer for reasons no one notices. Maybe it’s a specific product SKU. Maybe it’s tickets that come in during a certain timezone. Maybe it’s a particular integration that’s secretly broken.&lt;/p&gt;

&lt;p&gt;These patterns are invisible until AI finds them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What AI can do:&lt;/strong&gt; Pattern recognition tools can reveal connections like: &lt;em&gt;“Tickets mentioning SSO integration have 3x longer resolution times.”&lt;/em&gt; Now you know where to focus your improvement efforts.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Big Picture
&lt;/h3&gt;

&lt;p&gt;GenAI isn’t just about deploying a chatbot and calling it a day. It’s about building intelligent systems that:&lt;/p&gt;

&lt;p&gt;✅ Understand what customers actually &lt;em&gt;mean&lt;/em&gt;, not just what they say&lt;br&gt;&lt;br&gt;
 ✅ Predict problems before they spiral&lt;br&gt;&lt;br&gt;
 ✅ Coach your team to be more empathetic and effective&lt;br&gt;&lt;br&gt;
 ✅ Keep your knowledge base alive and useful (automatically)&lt;br&gt;&lt;br&gt;
 ✅ Uncover the root causes slowing everything down&lt;/p&gt;

&lt;p&gt;In other words: &lt;strong&gt;AI helps you move from reactive firefighting to proactive problem-solving.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And here’s what matters most: your agents get to spend less time on repetitive busywork and more time actually connecting with customers. Because at the end of the day, that’s what great support is really about.&lt;/p&gt;

&lt;h3&gt;
  
  
  What’s Coming Next
&lt;/h3&gt;

&lt;p&gt;Over the next few weeks, we’ll break down each of these pain points in detail. We’ll show you real examples, practical tools, and implementation strategies (not theoretical fluff, but things you can actually use).&lt;/p&gt;

&lt;p&gt;What pain point hits closest to home for you? Reply and let me know. I read every message.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/reimagining-customer-support-with-genai/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on October 29, 2025.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>ticketingsystem</category>
      <category>customerexperience</category>
      <category>customersuccess</category>
      <category>customerservice</category>
    </item>
    <item>
      <title>Create an Adaptive Customer Behavior Analytics Dashboard with Claude AI and Python</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Thu, 30 Jan 2025 12:35:24 +0000</pubDate>
      <link>https://dev.to/kadnan/create-an-adaptive-customer-behavior-analytics-dashboard-with-claude-ai-and-python-1e02</link>
      <guid>https://dev.to/kadnan/create-an-adaptive-customer-behavior-analytics-dashboard-with-claude-ai-and-python-1e02</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jnbayhjr5gazrznv8d9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jnbayhjr5gazrznv8d9.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://blog.adnansiddiqi.me/generate-stunning-avatars-using-openai-apis/" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, I introduced OpenAI’s image APIs and used them to create avatars. Today, I’m diving into another LLM service, &lt;a href="https://claude.ai/" rel="noopener noreferrer"&gt;ClaudeAI&lt;/a&gt;, which has gained traction for its speed and sharp analytical responses. I asked Claude to brainstorm ideas for my next blog post about itself. Among many fantastic suggestions, I chose &lt;em&gt;Customer Behavior Analysis&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Finding a suitable dataset on Kaggle was easy, but the real challenge began when I started working on it. I didn’t expect it to take 4–5 hours to achieve my goal. Initially, I had no clear idea how to use Claude for this, but Claude itself guided me, step by step, on the best approach. As I got deeper, the problem turned into an exciting puzzle; it was challenging, yet fun; thanks to Claude’s capabilities.&lt;/p&gt;

&lt;p&gt;Curious why it took so long and how it all worked? Keep reading, or jump straight to the demo video if you’re in a hurry or not interested:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/fdd787667b8a1ee0842e7fbd33d0dc6e/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/fdd787667b8a1ee0842e7fbd33d0dc6e/href" rel="noopener noreferrer"&gt;https://medium.com/media/fdd787667b8a1ee0842e7fbd33d0dc6e/href&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before discussing the project, let me tell you what Customer Behaviour Analysis is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Customer Behaviour Analytics
&lt;/h3&gt;

&lt;p&gt;Customer Behavior Analysis(CBA) involves collecting and studying data to understand how customers interact with a business, including their engagement with products, services, marketing, and website features.&lt;/p&gt;

&lt;p&gt;Simply put, CBA is a kind of &lt;a href="https://blog.adnansiddiqi.me/introduction-to-exploratory-data-analysis-in-python/" rel="noopener noreferrer"&gt;exploratory data analysis&lt;/a&gt; in which you use shopping data to find insights about your business.&lt;/p&gt;

&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Before proceeding, let’s clarify what we’re building. The title mentions &lt;em&gt;adaptive&lt;/em&gt; which means our system doesn’t rely on a fixed data schema. Instead, it analyzes the data and generates a dashboard dynamically. For example, websites A and B might store orders and products differently in their databases. When both CSVs are uploaded, our system uses Claude to interpret the schemas, generates Python code, executes it, and returns computed data to Claude. Claude then creates the HTML and JS for the dashboard at runtime. The steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Upload the CSV file via the web interface.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Convert the CSV to JSON for Claude.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Writing Prompt&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Send JSON with a prompt to Claude to generate Python code dynamically.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Execute the generated Python code to create a partially pre-defined JSON structure.&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Send the resulting JSON to Claude, which generates and renders the HTML and JS for the dashboard.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am using &lt;a href="https://blog.adnansiddiqi.me/tag/flask/" rel="noopener noreferrer"&gt;Flask&lt;/a&gt; for the web app, which is ideal for building prototypes like this. Now, let’s get into development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Web Interface for CSV Upload
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ivch1yd6fa77mpxmyoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ivch1yd6fa77mpxmyoi.png" width="800" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s a basic web interface for uploading CSV files. It sends an AJAX request to the /upload endpoint, where the file is renamed and saved. The process happens entirely in the /upload endpoint, which we'll break down step by step.&lt;/p&gt;

&lt;h4&gt;
  
  
  Converting CSV to JSON for Claude
&lt;/h4&gt;

&lt;p&gt;To inform our first prompt about the data structure, we don’t need to send the entire file. The goal is to provide Claude with the column names and their types so it can generate the relevant Python code. As of January 2025, Claude cannot execute code directly from data input. To address this, we’ll create a function called extract_sample_data. Oh, BTW, I have used &lt;a href="https://www.kaggle.com/datasets/zeesolver/consumer-behavior-and-shopping-habits-dataset" rel="noopener noreferrer"&gt;this&lt;/a&gt; Kaggle dataset and another( &lt;em&gt;randomly generated by GPT&lt;/em&gt;)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def extract_sample_data(file_path, num_rows=5):
    try:
        # Load the CSV file
        df = pd.read_csv(file_path)

        # Extract the first few rows
        sample_data = df.head(num_rows).to_dict(orient='records')

        # Get column data types
        column_types = {col: str(df[col].dtype) for col in df.columns}
        del df
        gc.collect()
        return {
            "sample_data": sample_data,
            "column_types": column_types
        }
    except Exception as e:
        print(f"Error: {e}")
        return None
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function will extract the first &lt;em&gt;nth&lt;/em&gt; rows and their data types and return a &lt;em&gt;Dict&lt;/em&gt; object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  'sample_data': [
    {
      'Customer ID': 1,
      'Age': 55,
      'Gender': 'Male',
      'Item Purchased': 'Blouse',
      'Category': 'Clothing',
      'Purchase Amount (USD)': 53,
      'Location': 'Kentucky',
      'Size': 'L',
      'Color': 'Gray',
      'Season': 'Winter',
      'Review Rating': 3.1,
      'Subscription Status': 'Yes',
      'Shipping Type': 'Express',
      'Discount Applied': 'Yes',
      'Promo Code Used': 'Yes',
      'Previous Purchases': 14,
      'Payment Method': 'Venmo',
      'Frequency of Purchases': 'Fortnightly'
    },
    {
      'Customer ID': 2,
      'Age': 19,
      'Gender': 'Male',
      'Item Purchased': 'Sweater',
      'Category': 'Clothing',
      'Purchase Amount (USD)': 64,
      'Location': 'Maine',
      'Size': 'L',
      'Color': 'Maroon',
      'Season': 'Winter',
      'Review Rating': 3.1,
      'Subscription Status': 'Yes',
      'Shipping Type': 'Express',
      'Discount Applied': 'Yes',
      'Promo Code Used': 'Yes',
      'Previous Purchases': 2,
      'Payment Method': 'Cash',
      'Frequency of Purchases': 'Fortnightly'
    }
  ],
  'column_types': {
    'Customer ID': 'int64',
    'Age': 'int64',
    'Gender': 'object',
    'Item Purchased': 'object',
    'Category': 'object',
    'Purchase Amount (USD)': 'int64',
    'Location': 'object',
    'Size': 'object',
    'Color': 'object',
    'Season': 'object',
    'Review Rating': 'float64',
    'Subscription Status': 'object',
    'Shipping Type': 'object',
    'Discount Applied': 'object',
    'Promo Code Used': 'object',
    'Previous Purchases': 'int64',
    'Payment Method': 'object',
    'Frequency of Purchases': 'object'
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, it returned two records, which are sufficient for Claude to identify the structure and data types. Knowing the data types is essential for generating Python code tailored to the available data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Prompt for Python Code Generation
&lt;/h4&gt;

&lt;p&gt;Now we have to come up with a prompt. If you do not know what &lt;a href="https://blog.adnansiddiqi.me/introduction-to-prompt-engineering/" rel="noopener noreferrer"&gt;prompt engineering&lt;/a&gt; is, check it out!&lt;/p&gt;

&lt;p&gt;So, the goal is to come up with a Claude prompt that will accept the schema we generated above and produce Python code. The goal is to generate Python code that can show both text and graphs. I took the help of both GPT and Claude to generate the first prompt which is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You are a Python data analyst tasked with creating dynamic analysis code. I will provide you with a JSON structure containing field names and their data types. Your task is to generate a Python script that reads a CSV file, performs flexible analysis based on the dataset, and returns the output strictly in a JSON payload format.

{FIELDS_AND_TYPES}

### **Output Requirements**

1. **If Required Fields Are Missing:**
   - The generated script should validate the presence of required fields in the CSV file.
   - If any required fields are missing, the script should return:
     ```

json
     {
       "error": "true",
       "message": "&amp;lt;Explanation of missing fields or sections&amp;gt;"
     }


     ```

2. **If Code Is Successfully Generated:**
   - Return a JSON payload with:
     ```

json
     {
       "error": "false",
       "message": "&amp;lt;Entire Python code including imports, main function, and execution block&amp;gt;"
     }


     ```

3. **Additional Requirements:**
   - Do not include any explanatory text, comments, or preambles in the response.
   - Avoid any prefixes like "Here's the code" or suffixes explaining the output.
   - Only output the final JSON payload.

### **Code Requirements**
- **Input Handling:**
  - The generated code should accept a CSV file as input and load it into a Pandas DataFrame.
  - Include error handling for missing or malformed CSV files.

- **Field Validation:**
  - Validate the presence of required fields in the CSV file:
    - Demographic Analysis: Requires `age`, `gender`, `location`.
    - Behavioral Analysis: Requires `frequency`, `previous purchases`, `subscription status`.
    - Purchase Patterns: Requires `amount`, `date`, `category`, `discount`.
    - Product Preferences: Requires `item`, `size`, `color`, `season`.
    - Response Analysis: Requires `rating`, `reviews`.
  - If required fields are missing, the script should log the missing fields and skip the related analysis.

- **Modular Analysis:**
  - The script must perform modular analysis based on available fields:
    - Summary statistics
    - Segmentation and profiling
    - Behavioral and purchase pattern analysis
    - Product preference and response analysis
  - Each module should check for the required fields before execution and log skipped modules.

- **Visualization:**
  - The script must generate visualizations dynamically based on the dataset.
  - Save visualizations as base64-encoded strings for JSON compatibility.

- **Output:**
  - The script should return analysis results in a JSON-compatible dictionary with the following structure:
    ```

json
    {
      "error": false,
      "results": {
        "summary_statistics": {...},
        "segmentation_results": {...},
        "behavioral_analysis": {...},
        "purchase_patterns": {...},
        "product_preferences": {...},
        "visualizations": [...]
      }
    }


    ```

### **Response Examples**

#### **Error Output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
json&lt;br&gt;
{&lt;br&gt;
  "error": "true",&lt;br&gt;
  "message": "Missing required fields: ['age', 'gender', 'location']"&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
I pass the previously generated schema, along with instructions and sample output, to the prompt. The code must produce an output similar to the example below, where the inner fields may vary, but the main structure remains consistent. If the required CSV file is missing, the prompt will generate a relevant JSON error message.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;{&lt;br&gt;
  "error": false,&lt;br&gt;
  "results": {&lt;br&gt;
    "summary_statistics": {&lt;br&gt;
      ...&lt;br&gt;
    },&lt;br&gt;
    "segmentation_results": {&lt;br&gt;
      ...&lt;br&gt;
    },&lt;br&gt;
    "behavioral_analysis": {&lt;br&gt;
      ...&lt;br&gt;
    },&lt;br&gt;
    "purchase_patterns": {&lt;br&gt;
      ...&lt;br&gt;
    },&lt;br&gt;
    "product_preferences": {&lt;br&gt;
      ...&lt;br&gt;
    },&lt;br&gt;
    "visualizations": [&lt;br&gt;
      ...&lt;br&gt;
    ]&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The code accepts a CSV file, loads it into Pandas, and generates text and graphs.

An early output of the prompt was:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;{&lt;br&gt;
  'error': 'false',&lt;br&gt;
  'message': "import pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport base64\nfrom io import BytesIO\n\ndef encode_plot(plt):\n buffer = BytesIO()\n plt.savefig(buffer, format='png', bbox_inches='tight')\n buffer.seek(0)\n image_png = buffer.getvalue()\n buffer.close()\n plt.close()\n return base64.b64encode(image_png).decode()\n\ndef analyze_data(csv_file):\n try:\n df = pd.read_csv(csv_file)\n results = {\n 'error': False,\n 'results': {\n 'summary_statistics': {},\n 'segmentation_results': {},\n 'behavioral_analysis': {},\n 'purchase_patterns': {},\n 'product_preferences': {},\n 'visualizations': []\n }\n }\n \n # Validate required fields\n required_fields = {\n 'demographic': ['Age', 'Gender', 'Location'],\n 'behavioral': ['Frequency of Purchases', 'Previous Purchases', 'Subscription Status'],\n 'purchase': ['Purchase Amount (USD)', 'Category', 'Discount Applied'],\n 'product': ['Item Purchased', 'Size', 'Color', 'Season'],\n 'response': ['Review Rating']\n }\n \n for category, fields in required_fields.items():\n if not all(field in df.columns for field in fields):\n return {\n 'error': True,\n 'message': f'Missing required fields for {category} analysis: {[f for f in fields if f not in df.columns]}'\n }\n \n # Summary Statistics\n results['results']['summary_statistics'] = {\n 'total_customers': len(df),\n 'average_purchase': float(df['Purchase Amount (USD)'].mean()),\n 'average_rating': float(df['Review Rating'].mean()),\n 'total_revenue': float(df['Purchase Amount (USD)'].sum())\n }\n \n # Segmentation Results\n age_segments = df.groupby(pd.cut(df['Age'], bins=[0, 25, 50, 75, 100])).size().to_dict()\n results['results']['segmentation_results'] = {\n 'age_distribution': {str(k): int(v) for k, v in age_segments.items()},\n 'gender_distribution': df['Gender'].value_counts().to_dict()\n }\n \n # Behavioral Analysis\n results['results']['behavioral_analysis'] = {\n 'purchase_frequency': df['Frequency of Purchases'].value_counts().to_dict(),\n 'avg_previous_purchases': float(df['Previous Purchases'].mean())\n }\n \n # Purchase Patterns\n results['results']['purchase_patterns'] = {\n 'category_distribution': df['Category'].value_counts().to_dict(),\n 'avg_amount_by_category': df.groupby('Category')['Purchase Amount (USD)'].mean().to_dict()\n }\n \n # Product Preferences\n results['results']['product_preferences'] = {\n 'popular_colors': df['Color'].value_counts().to_dict(),\n 'size_distribution': df['Size'].value_counts().to_dict(),\n 'seasonal_preference': df['Season'].value_counts().to_dict()\n }\n \n # Visualizations\n plt.figure(figsize=(10, 6))\n sns.histplot(data=df, x='Age', bins=20)\n plt.title('Age Distribution')\n results['results']['visualizations'].append({\n 'title': 'age_distribution',\n 'image': encode_plot(plt)\n })\n \n plt.figure(figsize=(10, 6))\n sns.boxplot(data=df, x='Category', y='Purchase Amount (USD)')\n plt.xticks(rotation=45)\n plt.title('Purchase Amount by Category')\n results['results']['visualizations'].append({\n 'title': 'purchase_by_category',\n 'image': encode_plot(plt)\n })\n \n return results\n \n except Exception as e:\n return {\n 'error': True,\n 'message': f'Error analyzing data: {str(e)}'\n }\n\ndef main(csv_file):\n return analyze_data(csv_file)\n\nif &lt;strong&gt;name&lt;/strong&gt; == ' &lt;strong&gt;main&lt;/strong&gt;':\n import sys\n if len(sys.argv) &amp;gt; 1:\n result = main(sys.argv[1])\n print(result)\n else:\n print({'error': True, 'message': 'No CSV file provided'})"&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
When you run the above code, it produces the output like this:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;[&lt;br&gt;
  TextBlock(text='{\n "error": false,\n "message": "Analysis code generated successfully",\n "code": {\n "imports": """\nimport pandas as pd\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport json\nimport base64\nfrom io import BytesIO\nimport os\n""",\n "main_analysis": """\ndef analyze_retail_data(data_json):\n # Convert JSON to DataFrame\n df = pd.DataFrame(data_json[\'sample_data\'])\n \n # Create results dictionary\n results = {\n "error": False,\n "message": "Analysis completed successfully",\n "results": {}\n }\n \n # Create visualization directory if it doesn\'t exist\n os.makedirs(\'visualizations\', exist_ok=True)\n \n # Summary Statistics\n numerical_cols = [\'Age\', \'Purchase Amount (USD)\', \'Review Rating\', \'Previous Purchases\']\n results[\'results\'][\'summary_statistics\'] = {\n col: df[col].describe().to_dict() for col in numerical_cols\n }\n \n # Segmentation Results\n results[\'results\'][\'segmentation_results\'] = {\n \'gender_distribution\': df[\'Gender\'].value_counts().to_dict(),\n \'age_segments\': pd.qcut(df[\'Age\'], q=3, labels=[\'Young\', \'Middle\', \'Senior\']).value_counts().to_dict()\n }\n \n # Behavioral Analysis\n results[\'results\'][\'behavioral_analysis\'] = {\n \'subscription_status\': df[\'Subscription Status\'].value_counts().to_dict(),\n \'purchase_frequency\': df[\'Frequency of Purchases\'].value_counts().to_dict()\n }\n \n # Purchase Patterns\n results[\'results\'][\'purchase_patterns\'] = {\n \'seasonal_distribution\': df[\'Season\'].value_counts().to_dict(),\n \'payment_methods\': df[\'Payment Method\'].value_counts().to_dict(),\n \'shipping_preferences\': df[\'Shipping Type\'].value_counts().to_dict()\n }\n \n # Product Preferences\n results[\'results\'][\'product_preferences\'] = {\n \'popular_items\': df[\'Item Purchased\'].value_counts().to_dict(),\n \'size_distribution\': df[\'Size\'].value_counts().to_dict(),\n \'color_preferences\': df[\'Color\'].value_counts().to_dict()\n }\n \n # Visualizations\n results[\'results\'][\'visualizations\'] = []\n \n # Age vs Purchase Amount\n plt.figure(figsize=(10, 6))\n sns.scatterplot(data=df, x=\'Age\', y=\'Purchase Amount (USD)\')\n plt.title(\'Age vs Purchase Amount\')\n \n # Save plot as base64\n buffer = BytesIO()\n plt.savefig(buffer, format=\'png\')\n buffer.seek(0)\n image_png = buffer.getvalue()\n buffer.close()\n \n # Encode to base64\n graphic = base64.b64encode(image_png).decode(\'utf-8\')\n results[\'results\'][\'visualizations\'].append({\n \'type\': \'scatter_plot\',\n \'title\': \'Age vs Purchase Amount\',\n \'base64_image\': graphic\n })\n \n # Category Distribution\n plt.figure(figsize=(10, 6))\n sns.countplot(data=df, x=\'Category\')\n plt.title(\'Category Distribution\')\n plt.xticks(rotation=45)\n \n # Save plot as base64\n buffer = BytesIO()\n plt.savefig(buffer, format=\'png\')\n buffer.seek(0)\n image_png = buffer.getvalue()\n buffer.close()\n \n # Encode to base64\n graphic = base64.b64encode(image_png).decode(\'utf-8\')\n results[\'results\'][\'visualizations\'].append({\n \'type\': \'bar_plot\',\n \'title\': \'Category Distribution\',\n \'base64_image\': graphic\n })\n \n return results\n""",\n "execution": """\nif &lt;strong&gt;name&lt;/strong&gt; == " &lt;strong&gt;main&lt;/strong&gt;":\n # Rea',&lt;br&gt;
  type='text')&lt;br&gt;
]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Another variation of the generated code output is shown below:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;{&lt;br&gt;
  'error': False,&lt;br&gt;
  'results': {&lt;br&gt;
    'summary_statistics': {&lt;br&gt;
      'total_customers': 3900,&lt;br&gt;
      'average_purchase': 59.76435897435898,&lt;br&gt;
      'average_rating': 3.7499487179487176,&lt;br&gt;
      'total_revenue': 233081.0&lt;br&gt;
    },&lt;br&gt;
    'segmentation_results': {&lt;br&gt;
      'age_distribution': {&lt;br&gt;
        '(0, 25]': 571,&lt;br&gt;
        '(25, 50]': 1853,&lt;br&gt;
        '(50, 75]': 1476,&lt;br&gt;
        '(75, 100]': 0&lt;br&gt;
      },&lt;br&gt;
      'gender_distribution': {&lt;br&gt;
        'Male': 2652,&lt;br&gt;
        'Female': 1248&lt;br&gt;
      }&lt;br&gt;
    },&lt;br&gt;
    'behavioral_analysis': {&lt;br&gt;
      'purchase_frequency': {&lt;br&gt;
        'Every 3 Months': 584,&lt;br&gt;
        'Annually': 572,&lt;br&gt;
        'Quarterly': 563,&lt;br&gt;
        'Monthly': 553,&lt;br&gt;
        'Bi-Weekly': 547,&lt;br&gt;
        'Fortnightly': 542,&lt;br&gt;
        'Weekly': 539&lt;br&gt;
      },&lt;br&gt;
      'avg_previous_purchases': 25.35153846153846&lt;br&gt;
    },&lt;br&gt;
    'purchase_patterns': {&lt;br&gt;
      'category_distribution': {&lt;br&gt;
        'Clothing': 1737,&lt;br&gt;
        'Accessories': 1240,&lt;br&gt;
        'Footwear': 599,&lt;br&gt;
        'Outerwear': 324&lt;br&gt;
      },&lt;br&gt;
      'avg_purchase_by_category': {&lt;br&gt;
        'Accessories': 59.83870967741935,&lt;br&gt;
        'Clothing': 60.025331030512376,&lt;br&gt;
        'Footwear': 60.25542570951586,&lt;br&gt;
        'Outerwear': 57.17283950617284&lt;br&gt;
      }&lt;br&gt;
    },&lt;br&gt;
    'product_preferences': {&lt;br&gt;
      'popular_colors': {&lt;br&gt;
        'Olive': 177,&lt;br&gt;
        'Yellow': 174,&lt;br&gt;
        'Silver': 173,&lt;br&gt;
        'Teal': 172,&lt;br&gt;
        'Green': 169,&lt;br&gt;
        'Black': 167,&lt;br&gt;
        'Cyan': 166,&lt;br&gt;
        'Violet': 166,&lt;br&gt;
        'Gray': 159,&lt;br&gt;
        'Maroon': 158,&lt;br&gt;
        'Orange': 154,&lt;br&gt;
        'Charcoal': 153,&lt;br&gt;
        'Pink': 153,&lt;br&gt;
        'Magenta': 152,&lt;br&gt;
        'Blue': 152,&lt;br&gt;
        'Purple': 151,&lt;br&gt;
        'Peach': 149,&lt;br&gt;
        'Red': 148,&lt;br&gt;
        'Beige': 147,&lt;br&gt;
        'Indigo': 147,&lt;br&gt;
        'Lavender': 147,&lt;br&gt;
        'Turquoise': 145,&lt;br&gt;
        'White': 142,&lt;br&gt;
        'Brown': 141,&lt;br&gt;
        'Gold': 138&lt;br&gt;
      },&lt;br&gt;
      'size_distribution': {&lt;br&gt;
        'M': 1755,&lt;br&gt;
        'L': 1053,&lt;br&gt;
        'S': 663,&lt;br&gt;
        'XL': 429&lt;br&gt;
      },&lt;br&gt;
      'seasonal_preference': {&lt;br&gt;
        'Spring': 999,&lt;br&gt;
        'Fall': 975,&lt;br&gt;
        'Winter': 971,&lt;br&gt;
        'Summer': 955&lt;br&gt;
      }&lt;br&gt;
    },&lt;br&gt;
    'visualizations': [&lt;br&gt;
      {&lt;br&gt;
        'title': 'age_distribution',&lt;br&gt;
        'image': 'iVBORw0KGgoAAAANSUhEUgAAA1IAAAIjCAYAAAAJLyrXAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAA43UlEQVR4nO3de7hVBb3v4e9CYIFyE7mnXLwiqelWIrZdvBBo1ImkUtPCS1YGpmJlnu19V3TTrDZJdRTsSbdpqZm7MASlY5IpbTUUSdwYJiwQCRYgIrDG+aPHeVoB6kBkTljv+zzzeZhjjDnnb8pg1WeNMcesK4qiCAAAAK9bq2oPAAAAsKMRUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAOw0nnnmmdTV1WXKlClv+mtNmTIldXV1eeaZZyrL+vfvn/e///1v+msnyX333Ze6urrcd9992+X1AGhOSAHQzPe///3U1dVlyJAh1R4ldXV1lVvr1q3TtWvXHH744Tn33HPzxBNPbLPX+f73v79d4mtr1PJsAC1ZXVEURbWHAKB2HHnkkVm0aFGeeeaZPPXUU9l3332rNktdXV3e+9735hOf+ESKosjKlSvz6KOP5tZbb82aNWvy9a9/PePHj69sXxRF1q1blzZt2mSXXXZ53a9z0EEHpVu3bqWO7mzcuDHr169PfX196urqkvz9iNRBBx2Uu+6663U/z9bO1tTUlJdffjlt27ZNq1Z+LwqwvfnJC0DFggUL8sADD+Tqq69O9+7dc+ONN1Z7pOy///459dRT8/GPfzzjxo3Lj370ozz99NMZPHhwLrjggvzqV7+qbFtXV5d27dqViqiy1qxZkyTZZZdd0q5du0pEbW+tWrVKu3btRBRAlfjpC0DFjTfemN133z0jR47Mhz/84S2G1AsvvJCPf/zj6dSpU7p06ZIxY8bk0Ucf3eznk5588sl8+MMfTteuXdOuXbscccQRufPOO9/QnHvssUduvvnmtG7dOl/5ylcqyzf3GamGhoacfvrp2XPPPVNfX5/evXvngx/8YOWzTf3798/jjz+emTNnVk4jPOqoo5L8/89BzZw5M5/97GfTo0eP7Lnnns3W/eNnpF7xm9/8JoceemjatWuXQYMG5bbbbmu2/vLLL99sgP3zc77abFv6jNStt96aww8/PO3bt0+3bt1y6qmn5rnnnmu2zWmnnZYOHTrkueeey6hRo9KhQ4d07949n//857Nx48bX+K8PQJK0rvYAANSOG2+8MSeccELatm2bk08+Oddee20eeuihDB48uLJNU1NTPvCBD+QPf/hDzj777AwcODC/+MUvMmbMmE2e7/HHH8+RRx6Zt7zlLfnSl76U3XbbLbfccktGjRqVn//85/nQhz601bP27ds373nPe3LvvfemsbExnTp12ux2o0ePzuOPP55zzjkn/fv3z9KlSzNt2rQsXLgw/fv3zzXXXJNzzjknHTp0yL/9278lSXr27NnsOT772c+me/fuufTSSytHpLbkqaeeyoknnpjPfOYzGTNmTCZPnpyPfOQjmTp1at773veWeo+vZ7Z/NGXKlJx++ukZPHhwJkyYkCVLluQ73/lOfve73+W///u/06VLl8q2GzduzIgRIzJkyJB861vfyj333JOrrroq++yzT84+++xScwK0SAUAFEXx8MMPF0mKadOmFUVRFE1NTcWee+5ZnHvuuc22+/nPf14kKa655prKso0bNxbHHHNMkaSYPHlyZfmxxx5bHHzwwcVLL71UWdbU1FT867/+a7Hffvu95kxJirFjx25x/bnnnlskKR599NGiKIpiwYIFzWb429/+ViQpvvnNb77q67z1rW8t3vOe92yyfPLkyUWS4p3vfGexYcOGza5bsGBBZVm/fv2KJMXPf/7zyrKVK1cWvXv3Lg477LDKsssuu6zY3P8Eb+45tzTbvffeWyQp7r333qIoiuLll18uevToURx00EHF2rVrK9vdddddRZLi0ksvrSwbM2ZMkaS48sormz3nYYcdVhx++OGbvBYAm3JqHwBJ/n40qmfPnjn66KOT/P3zRieeeGJuvvnmZqd7TZ06NW3atMlZZ51VWdaqVauMHTu22fMtX748M2bMyEc/+tGsWrUqy5Yty7Jly/LCCy9kxIgReeqppzY55aysDh06JElWrVq12fXt27dP27Ztc9999+Vvf/vbVr/OWWed9bo/d9WnT59mR9o6deqUT3ziE/nv//7vNDQ0bPUMr+Xhhx/O0qVL89nPfjbt2rWrLB85cmQGDhyY//qv/9rkMZ/5zGea3X/Xu96V//mf/3nTZgTYmQgpALJx48bcfPPNOfroo7NgwYLMnz8/8+fPz5AhQ7JkyZJMnz69su1f/vKX9O7dO7vuumuz5/jnq/vNnz8/RVHkkksuSffu3ZvdLrvssiTJ0qVL39Dcq1evTpJ07Nhxs+vr6+vz9a9/Pb/+9a/Ts2fPvPvd7843vvGN0kEzYMCA173tvvvuu8nnn/bff/8k2eznqbaVv/zlL0mSAw44YJN1AwcOrKx/Rbt27dK9e/dmy3bfffc3FJwALYnPSAGQGTNmZPHixbn55ptz8803b7L+xhtvzPDhw0s9Z1NTU5Lk85//fEaMGLHZbd7opdXnzJmTXXbZ5VVD57zzzssHPvCB3HHHHbn77rtzySWXZMKECZkxY0YOO+yw1/U67du3f0Nz/rMtXelve17o4c28siFASyCkAMiNN96YHj16ZOLEiZusu+2223L77bdn0qRJad++ffr165d77703L774YrOjUvPnz2/2uL333jtJ0qZNmwwbNmybz7xw4cLMnDkzQ4cO3eIRqVfss88+ueCCC3LBBRfkqaeeyqGHHpqrrroqP/nJT5JsOWy2xitH4v7xOf/85z8n+ftV+JK/H/lJkhUrVjS7AMQ/HzUqM1u/fv2SJPPmzcsxxxzTbN28efMq6wHYNpzaB9DCrV27Nrfddlve//7358Mf/vAmt3HjxmXVqlWVS5aPGDEi69evz49+9KPKczQ1NW0SYT169MhRRx2VH/zgB1m8ePEmr/v8889v9czLly/PySefnI0bN1auZrc5L774Yl566aVmy/bZZ5907Ngx69atqyzbbbfdsmLFiq2e5x8tWrQot99+e+V+Y2NjfvzjH+fQQw9Nr169KjMkyW9/+9vKdmvWrMkNN9ywyfO93tmOOOKI9OjRI5MmTWr23n79619n7ty5GTly5Na+JQA2wxEpgBbuzjvvzKpVq/K//tf/2uz6d7zjHZUv5z3xxBMzatSovP3tb88FF1yQ+fPnZ+DAgbnzzjuzfPnyJM2PoEycODHvfOc7c/DBB+ess87K3nvvnSVLlmTWrFn561//mkcfffQ15/vzn/+cn/zkJymKIo2NjXn00Udz6623ZvXq1bn66qtz3HHHvepjjz322Hz0ox/NoEGD0rp169x+++1ZsmRJTjrppMp2hx9+eK699tp8+ctfzr777psePXpsclTn9dp///1z5pln5qGHHkrPnj1z/fXXZ8mSJZk8eXJlm+HDh6dv374588wz84UvfCG77LJLrr/++nTv3j0LFy5s9nyvd7Y2bdrk61//ek4//fS85z3vycknn1y5/Hn//v1z/vnnb9X7AWALqnzVQACq7AMf+EDRrl27Ys2aNVvc5rTTTivatGlTLFu2rCiKonj++eeLj33sY0XHjh2Lzp07F6eddlrxu9/9rkhS3Hzzzc0e+/TTTxef+MQnil69ehVt2rQp3vKWtxTvf//7i5/97GevOVuSyq1Vq1ZFly5disMOO6w499xzi8cff3yT7f/58ufLli0rxo4dWwwcOLDYbbfdis6dOxdDhgwpbrnllmaPa2hoKEaOHFl07NixSFK53PgrlyN/6KGHNnmtLV3+fOTIkcXdd99dHHLIIUV9fX0xcODA4tZbb93k8bNnzy6GDBlStG3btujbt29x9dVXb/Y5tzTbP1/+/BU//elPi8MOO6yor68vunbtWpxyyinFX//612bbjBkzpthtt902mWlLl2UHYFN1RVEU1Uk4AHYmd9xxRz70oQ/l/vvvz5FHHlntcQDgTSWkACht7dq1za5kt3HjxgwfPjwPP/xwGhoatvlV7gCg1viMFAClnXPOOVm7dm2GDh2adevW5bbbbssDDzyQr371qyIKgBbBESkASrvpppty1VVXZf78+XnppZey77775uyzz864ceOqPRoAbBdCCgAAoCTfIwUAAFCSkAIAACjJxSaSNDU1ZdGiRenYsWOzL5IEAABalqIosmrVqvTp0yetWm35uJOQSrJo0aLstdde1R4DAACoEc8++2z23HPPLa4XUkk6duyY5O//sTp16lTlaQAAgGppbGzMXnvtVWmELRFSSeV0vk6dOgkpAADgNT/y42ITAAAAJQkpAACAkqoaUhMmTMjgwYPTsWPH9OjRI6NGjcq8efOabXPUUUelrq6u2e0zn/lMs20WLlyYkSNHZtddd02PHj3yhS98IRs2bNiebwUAAGhBqvoZqZkzZ2bs2LEZPHhwNmzYkP/9v/93hg8fnieeeCK77bZbZbuzzjorV155ZeX+rrvuWvnzxo0bM3LkyPTq1SsPPPBAFi9enE984hNp06ZNvvrVr27X9wMAALQMdUVRFNUe4hXPP/98evTokZkzZ+bd7353kr8fkTr00ENzzTXXbPYxv/71r/P+978/ixYtSs+ePZMkkyZNyoUXXpjnn38+bdu2fc3XbWxsTOfOnbNy5UoX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/vd5xzvekd/85jd54okncs8996Rnz5459NBD8+///u+58MILc/nll6dt27bVeGsAAMBOrKY+I7Vy5cokSdeuXZMks2fPzvr16zNs2LDKNgMHDkzfvn0za9asJMmsWbNy8MEHp2fPnpVtRowYkcbGxjz++OObfZ1169alsbGx2Q0AAOD1qpkv5G1qasp5552XI488MgcddFCSpKGhIW3btk2XLl2abduzZ880NDRUtvnHiHpl/SvrNmfChAm54oortvE7AGBHt3DhwixbtqzaY2Tu3LnVHgGA11AzITV27NjMmTMn999//5v+WhdddFHGjx9fud/Y2Ji99trrTX9dAGrXwoULM3DggVm79sVqj1Kxft3L1R4BgC2oiZAaN25c7rrrrvz2t7/NnnvuWVneq1evvPzyy1mxYkWzo1JLlixJr169Ktv84Q9/aPZ8r1zV75Vt/ll9fX3q6+u38bsAYEe2bNmyrF37YoaccVk69e5f1VkW/2lW5tz5Q1egBahhVQ2poihyzjnn5Pbbb899992XAQMGNFt/+OGHp02bNpk+fXpGjx6dJJk3b14WLlyYoUOHJkmGDh2ar3zlK1m6dGl69OiRJJk2bVo6deqUQYMGbd83BMAOr1Pv/una94CqztC4+Jmqvj4Ar62qITV27NjcdNNN+cUvfpGOHTtWPtPUuXPntG/fPp07d86ZZ56Z8ePHp2vXrunUqVPOOeecDB06NO94xzuSJMOHD8+gQYPy8Y9/PN/4xjfS0NCQiy++OGPHjnXUCQCAmuKzmDuPqobUtddemyQ56qijmi2fPHlyTjvttCTJt7/97bRq1SqjR4/OunXrMmLEiHz/+9+vbLvLLrvkrrvuytlnn52hQ4dmt912y5gxY3LllVdur7cBAACvyWcxdy5VP7XvtbRr1y4TJ07MxIkTt7hNv3798qtf/WpbjgYAANuUz2LuXGriYhMAANBS+CzmzqGmvpAXAABgRyCkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJTUutoDAMDcuXOrPUJNzADAjkNIAVA1a1e+kKQup556arVHqVi/7uVqjwDADkBIAVA1619claTIoR+7MN0HDKzqLIv/NCtz7vxhNmzYUNU5ANgxCCkAqq5Dj77p2veAqs7QuPiZqr4+ADsWF5sAAAAoSUgBAACUJKQAAABK8hkpAOB1qYVLxNfCDACJkAIAXoPL1ANsSkgBAK/KZeoBNiWkAIDXxWXqAf4/IcUOpVbOja+VOQAAqA4hxQ6hFs/PT5yjDwDQUlU1pH7729/mm9/8ZmbPnp3Fixfn9ttvz6hRoyrrTzvttNxwww3NHjNixIhMnTq1cn/58uU555xz8stf/jKtWrXK6NGj853vfCcdOnTYXm+D7aCWzs9PnKMPANDSVTWk1qxZk7e97W0544wzcsIJJ2x2m+OOOy6TJ0+u3K+vr2+2/pRTTsnixYszbdq0rF+/Pqeffno+9alP5aabbnpTZ6c6auH8/MQ5+gAALV1VQ+r444/P8ccf/6rb1NfXp1evXptdN3fu3EydOjUPPfRQjjjiiCTJ9773vbzvfe/Lt771rfTp02ebzwwAANCq2gO8lvvuuy89evTIAQcckLPPPjsvvPBCZd2sWbPSpUuXSkQlybBhw9KqVas8+OCDW3zOdevWpbGxsdkNAADg9arpkDruuOPy4x//ONOnT8/Xv/71zJw5M8cff3w2btyYJGloaEiPHj2aPaZ169bp2rVrGhoatvi8EyZMSOfOnSu3vfba6019HwAAwM6lpq/ad9JJJ1X+fPDBB+eQQw7JPvvsk/vuuy/HHnvsVj/vRRddlPHjx1fuNzY2iikAAOB1q+kjUv9s7733Trdu3TJ//vwkSa9evbJ06dJm22zYsCHLly/f4ueqkr9/7qpTp07NbgAAAK9XTR+R+md//etf88ILL6R3795JkqFDh2bFihWZPXt2Dj/88CTJjBkz0tTUlCFDhlRzVAAAasjcuXOrPUJNzMC2U9WQWr16deXoUpIsWLAgjzzySLp27ZquXbvmiiuuyOjRo9OrV688/fTT+eIXv5h99903I0aMSJIceOCBOe6443LWWWdl0qRJWb9+fcaNG5eTTjrJFfsAAMjalS8kqcupp55a7VEq1q97udojsA1UNaQefvjhHH300ZX7r3xuacyYMbn22mvz2GOP5YYbbsiKFSvSp0+fDB8+PP/+7//e7LukbrzxxowbNy7HHnts5Qt5v/vd72739wLVVgu/5aqFGWpZrfz3qZU5YGdRC/+mamGGWrX+xVVJihz6sQvTfcDAqs6y+E+zMufOH2bDhg1VnYNto6ohddRRR6Uoii2uv/vuu1/zObp27erLd2nR/Kat9tXi31Hi7wneqFr8t+3f9ZZ16NE3XfseUNUZGhc/U9XXZ9vaoT4jBWzKb9pqXy39HSX+nmBbqaV/2/5dw/YnpGAn4Tdtta8W/o4Sf0+wrdXCv23/rmH726Eufw4AAFALhBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlLRVIbX33nvnhRde2GT5ihUrsvfee7/hoQAAAGrZVoXUM888k40bN26yfN26dXnuuefe8FAAAAC1rHWZje+8887Kn+++++507ty5cn/jxo2ZPn16+vfvv82GAwAAqEWlQmrUqFFJkrq6uowZM6bZujZt2qR///656qqrttlwAAAAtahUSDU1NSVJBgwYkIceeijdunV7U4YCAACoZaVC6hULFizY1nMAAADsMLYqpJJk+vTpmT59epYuXVo5UvWK66+//g0PBgAAUKu2KqSuuOKKXHnllTniiCPSu3fv1NXVbeu5AAAAatZWhdSkSZMyZcqUfPzjH9/W8wAAANS8rfoeqZdffjn/+q//uq1nAQAA2CFsVUh98pOfzE033bStZwEAANghbNWpfS+99FJ++MMf5p577skhhxySNm3aNFt/9dVXb5PhAAAAatFWhdRjjz2WQw89NEkyZ86cZutceAIAANjZbVVI3Xvvvdt6DgAAgB3GVn1GCgAAoCXbqiNSRx999KuewjdjxoytHggAAKDWbVVIvfL5qFesX78+jzzySObMmZMxY8Zsi7kAAABq1laF1Le//e3NLr/88suzevXqNzQQAABArdumn5E69dRTc/3112/LpwQAAKg52zSkZs2alXbt2m3LpwQAAKg5W3Vq3wknnNDsflEUWbx4cR5++OFccskl22QwAACAWrVVIdW5c+dm91u1apUDDjggV155ZYYPH75NBgMAAKhVWxVSkydP3tZzAAAA7DC2KqReMXv27MydOzdJ8ta3vjWHHXbYNhkKAACglm1VSC1dujQnnXRS7rvvvnTp0iVJsmLFihx99NG5+eab07179205IwAAQE3Zqqv2nXPOOVm1alUef/zxLF++PMuXL8+cOXPS2NiYz33uc9t6RgAAgJqyVUekpk6dmnvuuScHHnhgZdmgQYMyceJEF5sAAAB2elt1RKqpqSlt2rTZZHmbNm3S1NT0hocCAACoZVsVUsccc0zOPffcLFq0qLLsueeey/nnn59jjz12mw0HAABQi7YqpP7jP/4jjY2N6d+/f/bZZ5/ss88+GTBgQBobG/O9731vW88IAABQU7bqM1J77bVX/vjHP+aee+7Jk08+mSQ58MADM2zYsG06HAAAQC0qdURqxowZGTRoUBobG1NXV5f3vve9Oeecc3LOOedk8ODBeetb35r/+3//75s1KwAAQE0oFVLXXHNNzjrrrHTq1GmTdZ07d86nP/3pXH311dtsOAAAgFpUKqQeffTRHHfccVtcP3z48MyePfsNDwUAAFDLSoXUkiVLNnvZ81e0bt06zz///BseCgAAoJaVCqm3vOUtmTNnzhbXP/bYY+ndu/cbHgoAAKCWlQqp973vfbnkkkvy0ksvbbJu7dq1ueyyy/L+979/mw0HAABQi0pd/vziiy/Obbfdlv333z/jxo3LAQcckCR58sknM3HixGzcuDH/9m//9qYMCgAAUCtKhVTPnj3zwAMP5Oyzz85FF12UoiiSJHV1dRkxYkQmTpyYnj17vimDAgAA1IrSX8jbr1+//OpXv8rf/va3zJ8/P0VRZL/99svuu+/+ZswHAABQc0qH1Ct23333DB48eFvOAgAAsEModbEJAAAAhBQAAEBpQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKqmpI/fa3v80HPvCB9OnTJ3V1dbnjjjuarS+KIpdeeml69+6d9u3bZ9iwYXnqqaeabbN8+fKccsop6dSpU7p06ZIzzzwzq1ev3o7vAgAAaGmqGlJr1qzJ2972tkycOHGz67/xjW/ku9/9biZNmpQHH3wwu+22W0aMGJGXXnqpss0pp5ySxx9/PNOmTctdd92V3/72t/nUpz61vd4CAADQArWu5osff/zxOf744ze7riiKXHPNNbn44ovzwQ9+MEny4x//OD179swdd9yRk046KXPnzs3UqVPz0EMP5YgjjkiSfO9738v73ve+fOtb30qfPn2223sBAABajpr9jNSCBQvS0NCQYcOGVZZ17tw5Q4YMyaxZs5Iks2bNSpcuXSoRlSTDhg1Lq1at8uCDD27xudetW5fGxsZmNwAAgNerZkOqoaEhSdKzZ89my3v27FlZ19DQkB49ejRb37p163Tt2rWyzeZMmDAhnTt3rtz22muvbTw9AACwM6vZkHozXXTRRVm5cmXl9uyzz1Z7JAAAYAdSsyHVq1evJMmSJUuaLV+yZEllXa9evbJ06dJm6zds2JDly5dXttmc+vr6dOrUqdkNAADg9arZkBowYEB69eqV6dOnV5Y1NjbmwQcfzNChQ5MkQ4cOzYoVKzJ79uzKNjNmzEhTU1OGDBmy3WcGAABahqpetW/16tWZP39+5f6CBQvyyCOPpGvXrunbt2/OO++8fPnLX85+++2XAQMG5JJLLkmfPn0yatSoJMmBBx6Y4447LmeddVYmTZqU9evXZ9y4cTnppJNcsQ8AAHjTVDWkHn744Rx99NGV++PHj0+SjBkzJlOmTMkXv/jFrFmzJp/61KeyYsWKvPOd78zUqVPTrl27ymNuvPHGjBs3Lscee2xatWqV0aNH57vf/e52fy8AAEDLUdWQOuqoo1IUxRbX19XV5corr8yVV165xW26du2am2666c0YDwAAYLNq9jNSAAAAtUpIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgpJoOqcsvvzx1dXXNbgMHDqysf+mllzJ27Njsscce6dChQ0aPHp0lS5ZUcWIAAKAlqOmQSpK3vvWtWbx4ceV2//33V9adf/75+eUvf5lbb701M2fOzKJFi3LCCSdUcVoAAKAlaF3tAV5L69at06tXr02Wr1y5Mtddd11uuummHHPMMUmSyZMn58ADD8zvf//7vOMd79jeowIAAC1EzR+Reuqpp9KnT5/svffeOeWUU7Jw4cIkyezZs7N+/foMGzassu3AgQPTt2/fzJo161Wfc926dWlsbGx2AwAAeL1qOqSGDBmSKVOmZOrUqbn22muzYMGCvOtd78qqVavS0NCQtm3bpkuXLs0e07NnzzQ0NLzq806YMCGdO3eu3Pbaa6838V0AAAA7m5o+te/444+v/PmQQw7JkCFD0q9fv9xyyy1p3779Vj/vRRddlPHjx1fuNzY2iikAAOB1q+kjUv+sS5cu2X///TN//vz06tUrL7/8clasWNFsmyVLlmz2M1X/qL6+Pp06dWp2AwAAeL12qJBavXp1nn766fTu3TuHH3542rRpk+nTp1fWz5s3LwsXLszQoUOrOCUAALCzq+lT+z7/+c/nAx/4QPr165dFixblsssuyy677JKTTz45nTt3zplnnpnx48ena9eu6dSpU84555wMHTrUFfsAAIA3VU2H1F//+tecfPLJeeGFF9K9e/e8853vzO9///t07949SfLtb387rVq1yujRo7Nu3bqMGDEi3//+96s8NQAAsLOr6ZC6+eabX3V9u3btMnHixEycOHE7TQQAALCDfUYKAACgFggpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABKElIAAAAlCSkAAICShBQAAEBJQgoAAKAkIQUAAFCSkAIAAChJSAEAAJQkpAAAAEoSUgAAACUJKQAAgJKEFAAAQElCCgAAoCQhBQAAUJKQAgAAKElIAQAAlCSkAAAAShJSAAAAJQkpAACAkoQUAABASUIKAACgJCEFAABQkpACAAAoSUgBAACUJKQAAABK2mlCauLEienfv3/atWuXIUOG5A9/+EO1RwIAAHZSO0VI/fSnP8348eNz2WWX5Y9//GPe9ra3ZcSIEVm6dGm1RwMAAHZCO0VIXX311TnrrLNy+umnZ9CgQZk0aVJ23XXXXH/99dUeDQAA2Am1rvYAb9TLL7+c2bNn56KLLqosa9WqVYYNG5ZZs2Zt9jHr1q3LunXrKvdXrlyZJGlsbHxzh30dVq9enSRZ/pd52bBubVVnaVz8lyTJyueeSpvWdWb5B7U0j1nMUlYtzWOW2p8lqa15zFL7syS1NY9ZdoBZGhYm+fv/D66F/z/+ygxFUbzqdnXFa21R4xYtWpS3vOUteeCBBzJ06NDK8i9+8YuZOXNmHnzwwU0ec/nll+eKK67YnmMCAAA7kGeffTZ77rnnFtfv8EektsZFF12U8ePHV+43NTVl+fLl2WOPPVJXV/3f4mwvjY2N2WuvvfLss8+mU6dO1R6HGmLf4NXYP9gS+wavxv7BltTavlEURVatWpU+ffq86nY7fEh169Ytu+yyS5YsWdJs+ZIlS9KrV6/NPqa+vj719fXNlnXp0uXNGrHmderUqSZ2WmqPfYNXY/9gS+wbvBr7B1tSS/tG586dX3ObHf5iE23bts3hhx+e6dOnV5Y1NTVl+vTpzU71AwAA2FZ2+CNSSTJ+/PiMGTMmRxxxRN7+9rfnmmuuyZo1a3L66adXezQAAGAntFOE1Iknnpjnn38+l156aRoaGnLooYdm6tSp6dmzZ7VHq2n19fW57LLLNjnNEewbvBr7B1ti3+DV2D/Ykh1139jhr9oHAACwve3wn5ECAADY3oQUAABASUIKAACgJCEFAABQkpDayU2YMCGDBw9Ox44d06NHj4waNSrz5s1rts1LL72UsWPHZo899kiHDh0yevToTb7gmJ3Ttddem0MOOaTyBXhDhw7Nr3/968p6+wav+NrXvpa6urqcd955lWX2j5br8ssvT11dXbPbwIEDK+vtGy3bc889l1NPPTV77LFH2rdvn4MPPjgPP/xwZX1RFLn00kvTu3fvtG/fPsOGDctTTz1VxYnZXvr377/Jz466urqMHTs2yY73s0NI7eRmzpyZsWPH5ve//32mTZuW9evXZ/jw4VmzZk1lm/PPPz+//OUvc+utt2bmzJlZtGhRTjjhhCpOzfay55575mtf+1pmz56dhx9+OMccc0w++MEP5vHHH09i3+DvHnroofzgBz/IIYcc0my5/aNle+tb35rFixdXbvfff39lnX2j5frb3/6WI488Mm3atMmvf/3rPPHEE7nqqquy++67V7b5xje+ke9+97uZNGlSHnzwwey2224ZMWJEXnrppSpOzvbw0EMPNfu5MW3atCTJRz7ykSQ74M+OghZl6dKlRZJi5syZRVEUxYoVK4o2bdoUt956a2WbuXPnFkmKWbNmVWtMqmj33Xcv/s//+T/2DYqiKIpVq1YV++23XzFt2rTiPe95T3HuuecWReFnR0t32WWXFW9729s2u86+0bJdeOGFxTvf+c4trm9qaip69epVfPOb36wsW7FiRVFfX1/853/+5/YYkRpy7rnnFvvss0/R1NS0Q/7scESqhVm5cmWSpGvXrkmS2bNnZ/369Rk2bFhlm4EDB6Zv376ZNWtWVWakOjZu3Jibb745a9asydChQ+0bJEnGjh2bkSNHNtsPEj87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'&lt;br&gt;
      },&lt;br&gt;
      {&lt;br&gt;
        'title': 'purchase_by_category',&lt;br&gt;
        'image': 'iVBORw0KGgoAAAANSUhEUgAAA1IAAAJYCAYAAABoytfVAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjkuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/TGe4hAAAACXBIWXMAAA9hAAAPYQGoP6dpAAB0JUlEQVR4nO3dd1iV9eP/8ddhEwo4QQwn7lGmpYjmCCU1lXKWuS0tt6WppaY5ysqZI82cWOnHkSspyZF7VOZeuVJBTQERQYT794c/zjdyxK3gOeDzcV1cF+e+73PzOsdzC6/zvu/3sRiGYQgAAAAAkG4Otg4AAAAAAFkNRQoAAAAATKJIAQAAAIBJFCkAAAAAMIkiBQAAAAAmUaQAAAAAwCSKFAAAAACYRJECAAAAAJMoUgAAAABgEkUKALKIDz/8UBaLRZcvX7Z1FDykU6dOyWKx6LPPPrN1FADAA6JIAcA9zJkzRxaLxfrl5uamkiVLqkePHoqKirJ1vCxnwIABslgsatWqla2jZIqpU6dqzpw5to5xVydOnFDXrl1VrFgxubm5ydPTU0FBQZo4caJu3Lhhen/2/FgB4FFxsnUAALB3I0aMUNGiRZWQkKDNmzdr2rRpWrNmjfbv368nnnjC1vGyBMMw9M0336hIkSJauXKlrl27ppw5c9o6VoaaOnWq8ubNqw4dOtg6ShqrV69WixYt5Orqqnbt2ql8+fK6efOmNm/erP79++vAgQOaMWOGqX3a62MFgEeJIgUA/6FBgwaqUqWKJKlLly7KkyePxo0bp++//16vvvrqQ+371q1bSklJkYuLS0ZEtVsbNmzQX3/9pZ9//lkhISFaunSp2rdvb+tY2d7JkyfVunVrFS5cWD///LMKFChgXde9e3cdP35cq1evtmHCzHX9+nV5eHjYOgaAbIpT+wDApLp160q6/UeqJNWuXVu1a9e+Y7sOHTqoSJEi1tv/vC5mwoQJKl68uFxdXXXw4EFJ0uHDh9WyZUvly5dP7u7uKlWqlN5///079hsdHa0OHTrI29tbXl5e6tixo+Lj49NsM3v2bNWtW1f58+eXq6urypYtq2nTpt2xr927dyskJER58+aVu7u7ihYtqk6dOqXZJiUlRRMmTFC5cuXk5uYmHx8fde3aVVevXk33cxYWFqayZcuqTp06Cg4OVlhY2B3bbNiwQRaLRYsWLdLw4cNVsGBB5cyZU82bN1dMTIwSExPVp08f5c+fXzly5FDHjh2VmJiYZh+3bt3SRx99ZH1uixQposGDB9+xncVi0YcffnhHhiJFiqQZZUk9vXPLli3q16+f8uXLJw8PD7388su6dOlSmvsdOHBAGzdutJ4KerfXxN2MHz9ehQsXlru7u2rVqqX9+/db182ePVsWi0W//fbbHfcbPXq0HB0dde7cuXvue+zYsYqLi9OsWbPSlKhUAQEB6t27d5qf91+vm/96rNHR0erTp4/8/f3l6uqqgIAAffLJJ0pJSUmzn7///ltt27aVp6envL291b59e+3du1cWi+WO0wZ//vln1axZUx4eHvL29lbTpk116NChNNukXkN48OBBvfbaa8qVK5dq1Kjx0M8hANwLI1IAYNKJEyckSXny5Hmg+8+ePVsJCQl688035erqqty5c+uPP/5QzZo15ezsrDfffFNFihTRiRMntHLlSo0aNSrN/Vu2bKmiRYtqzJgx+vXXX/XVV18pf/78+uSTT6zbTJs2TeXKlVOTJk3k5OSklStX6u2331ZKSoq6d+8uSbp48aLq16+vfPnyaeDAgfL29tapU6e0dOnSND+va9eumjNnjjp27KhevXrp5MmT+uKLL/Tbb79py5YtcnZ2vu/jTUxM1JIlS/TOO+9Ikl599VV17NhRkZGR8vX1vWP7MWPGyN3dXQMHDtTx48c1efJkOTs7y8HBQVevXtWHH36o7du3a86cOSpatKiGDh1qvW+XLl00d+5cNW/eXO+884527NihMWPG6NChQ1q2bJm5f6h/6Nmzp3LlyqVhw4bp1KlTmjBhgnr06KHvvvtOkjRhwgT17NlTOXLksJZfHx+f/9zvvHnzdO3aNXXv3l0JCQmaOHGi6tatq3379snHx0fNmzdX9+7dFRYWpkqVKqW5b1hYmGrXrq2CBQvec/8rV65UsWLFVL169XQ9zvS8bu73WOPj41WrVi2dO3dOXbt2VaFChbR161YNGjRIFy5c0IQJEyTdLueNGzfWzp079dZbb6l06dL6/vvv7zpKuW7dOjVo0EDFihXThx9+qBs3bmjy5MkKCgrSr7/+mubNCklq0aKFSpQoodGjR8swjId+DgHgngwAwF3Nnj3bkGSsW7fOuHTpknH27Fnj22+/NfLkyWO4u7sbf/31l2EYhlGrVi2jVq1ad9y/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U2/v3LlTO3bsUIMGDdJsV7FiRVWsWFFfffWVlixZotatW8vJ6b/fCx0wYIA8PDzUpUsXRUVF3bH+xIkTmjhxoqT0v26kez/Wli1batu2bQoPD79jXXR0tPV6tpCQECUlJWnmzJnW9SkpKZoyZUqa+xQoUEBPP/205s6dm+bn7d+/Xz/++KP13zw9HvQ5BIB74X8QAHhInTp10rhx4xQSEqLOnTvr4sWLmj59usqVK5dmAoj7mTRpkmrUqKFnnnlGb775pooWLapTp05p9erV+v33303lqV+/vlxcXNS4cWN17dpVcXFxmjlzpvLnz59mxGXu3LmaOnWqXn75ZRUvXlzXrl3TzJkz5enpaf0DtVatWuratavGjBmj33//XfXr15ezs7OOHTumxYsXa+LEiWrevPldcyxcuFCGYahJkyZ3Xd+wYUM5OTkpLCxMVatWNfUY7+app55S+/btNWPGDEVHR6tWrVrauXOn5s6dq9DQUNWpU8e6bZcuXdStWzc1a9ZM9erV0969exUeHq68efM+8M+vXLmypk2bppEjRyogIED58+e3fubYvQQEBKhGjRp66623lJiYqAkTJihPnjx3PTWuXbt2evfddyUp3aekFS9eXAsXLlSrVq1UpkwZtWvXTuXLl9fNmze1detWLV682Pq5Wel93dzvsfbv318rVqzQSy+9pA4dOqhy5cq6fv269u3bp//97386deqU8ubNq9DQUD333HN65513dPz4cZUuXVorVqzQlStXJKUd8fr000/VoEEDBQYGqnPnztbpz728vO76WWD38yDPIQDck62mCwQAe5c69fX9pgdPtWDBAqNYsWKGi4uL8fTTTxvh4eH3nP78008/ves+9u/fb7z88suGt7e34ebmZpQqVcoYMmSIdX3q9M6XLl26a86TJ09al61YscKoWLGi4ebmZhQpUsT45JNPjK+//jrNdr/++qvx6quvGoUKFTJcXV2N/PnzGy+99JKxe/fuO7LNmDHDqFy5suHu7m7kzJnTqFChgjFgwADj/Pnz93xOKlSoYBQqVOi+z1vt2rWN/PnzG0lJSdbpzxcvXnzXx/fvf4e7PR9JSUnG8OHDjaJFixrOzs6Gv7+/MWjQICMhISHNfZOTk4333nvPyJs3r/HEE08YISEhxvHjx+85/fm/f3Zq1vXr11uXRUZGGo0aNTJy5sxp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qA8//FDt2rWT9H+/A+Li4rRw4ULNmjVLx48f1+HDh5UvXz4bpwYy3unTp1W3bl317dtXPXr0sI5Q7dq1S88++6yio6O1fPly7dixQ76+vmrVqpVKly5t69iPPYoUMs27776rb7/91vphio6OjgoLC1NQUJC2bt2qiRMnatu2bfL09FRCQoIOHTokZ2dnW8cGMsWVK1es13Q88cQT2rhxo3x9fa0zlKX+0jx//ry++eYbvfTSSypVqpSNUwOZ45+zVvbp00eTJk3S8OHD9f7771vfPEgtU4ZhKCYmRvHx8Zziimxr3759evXVV7VixQp5enpq3rx5WrlypbZv3646depYPwpASnv8wLYoUsgU8+fPV9++fbVu3Tr5+fnJYrGoY8eO2r17t9atW6fy5ctr3759OnLkiE6fPq3evXvLycmJ6Z2RrV28eFHJyclq2rSprl69ql9++UW+vr7WUdzY2Fh5enryuTjItu71B2CPHj301Vdf6dtvv1VoaOh/bg9kdamv7ejoaHl7eysmJkb+/v569tlndezYMVWpUkVVqlRR1apV1bZtWw0fPlxvvPGGrWPjXyhSeGhLly5V3bp15e3tbV320UcfWT807p9/FNapU0c3btzQ9u3b79gPp/MhO0n9JXns2DFFR0fLYrGoYsWKcnFx0alTp9SyZUvFxMRYR6YmTJigM2fOaOzYsXJ0dOSPR2Q7qcfEli1btHnzZsXExKhcuXJq06aNJOmtt97S3Llz9e2336pJkyY2TgtkntRjYfXq1frss880atQoVa9eXceOHdPkyZPl7++vNm3ayNfXVw4ODgoJCVGTJk3UvXt3W0fHv/CWJx7K6tWr1bx5c02fPl2xsbHW5RcvXtSRI0ck3Z6ZLzExUZLUv39/RUVF6c8//7xjX5QoZBepvySXLFmiWrVqqW3btnruuefUokULLV26VEWKFNHixYuVN29elSxZUs2aNVP//v3Vvn17OTk5UaKQLVksFi1dulQNGzbUgQMHdPjwYY0cOVLNmzeXJE2bNk0dO3ZU27ZttXjxYhunBTJP6rHw6quvqlatWnJzc5MklShRQhMnTlT//v3l5+cnwzA0ePBg7d27Vw0aNLBxatwNRQoPpVGjRpo2bZoGDx6sL774QtHR0ZKkDh06KCkpScOGDZMk64fFubi4yNXVldKEbM1isVg/F23YsGH6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kerevbt1OSUK2cEff/yh6tWrq2fPnho/frx1eUhIiIoUKaKxY8cqKSnJOpFKnjx5lJKSolu3btkqMvBIOTg46JdfflG+fPn07rvvauPGjUpOTlbPnj31xRdfaNCgQXrxxRf12WefadasWfLy8uL3A7KN1DeNV65cqTfffFP/+9//lJycrPLlyys+Pl4+Pj56++235eDgoMTERA0dOlQbNmxQt27dKFFZGKf2wbTk5GTNnj1bb7/9tnx8fFS+fHmlpKQoJiZGKSkp2rJli5ydna0X3gNZ3dmzZ/XMM8+obt26+u6776zLJ0+erH379skwDJ04cUL169fXwIEDFRcXp48//lhLly7Vhg0blD9/fhumBzJH6h+O169fTzOhUHx8vGrXrq1bt27p888/1/PPPy9HR0ft2LFDp0+f1nPPPcd1gsiWVqxYoZYtW2rkyJFq2rSpSpQoIen29P5Tp05VTEyMihUrppSUFP32229au3atKlWqZOPUeBgUKTyw33//XV9//bWOHDkif39/VapUSd26deNzopDtnDp1Si1btlSBAgU0YMAABQUFacyYMRo1apQ2b96sIkWK6IMPPlBERITOnz+vsmXL6vjx4/rxxx/5JYlsbePGjRo4cKBmzJiRZta9GzduqFq1akpJSdGECRNUs2ZNubi42DApkLkiIyPVtGlTtWrVSv369btj/S+//KLffvtNv/32m5566im99NJLCggIsEFSZCSKFDIcI1HIjo4dO2ad2t/Hx0fff/+95s+fb510JS4uTpGRkfrhhx/k6+urKlWqMIUtsp0bN27IwcFBUVFR8vf3V2xsrEqWLKnSpUtr6tSpKleunHVmvgMHDqhy5coqU6aMJkyYoFq1atk6PpBpIiMjVa1aNU2aNElNmjS5Y/3Nmzd5MyEb4hopPJS79XBKFLKjEiVKaOLEibpx44YWLFigAQMGWEtUcnKycuTIoYCAAPXs2VMtWrSgRCHbOXTokF5//XVVqVJFxYsXV4UKFTR37lwdOXJEZ8+eVdeuXXXgwAE5ONz+0yIuLk6NGjVSzpw5VahQIRunBzLWv//+uXTpkq5fv2693ikxMdG67o8//tB3332XZhmyB4oUHgoXCuNxUrJkSU2bNk01a9ZURESENm/eLOn2mwcM7iM727dvnwIDA1WgQAH16dNHixYtUkBAgPr06aP+/ftr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'&lt;br&gt;
      }&lt;br&gt;
    ]&lt;br&gt;
  }&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
If you ask me, it almost achieved what I wanted; it generated stats and charts in base64 format. However, I wasn’t completely satisfied. I thought, why not have the code produce just the data and let JavaScript handle the chart generation?

Another crucial issue I faced was that the generated code didn’t accept CSV files with different names due to the following clause:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Field Validation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validate the presence of required fields in the CSV file:

&lt;ul&gt;
&lt;li&gt;Demographic Analysis: Requires &lt;code&gt;age&lt;/code&gt;, &lt;code&gt;gender&lt;/code&gt;, &lt;code&gt;location&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This caused the Python code to explicitly look for specific fields, defeating the purpose of the project. I wanted Claude to infer field names and adapt accordingly. After many iterations, the following prompt worked as intended:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are a Python data analyst tasked with creating dynamic analysis code. I will provide you with a dataset in CSV format. Your task is to generate a Python script that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dynamically identifies and categorizes fields based on their context and meaning in the dataset.&lt;/li&gt;
&lt;li&gt;Performs modular analysis for each category based on the available fields.&lt;/li&gt;
&lt;li&gt;Returns the output strictly in a JSON payload format.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;{FIELDS_AND_TYPES}&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Output Requirements&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If Required Fields Are Missing:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If no fields can be inferred for certain categories, return:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Unable to infer required fields for &amp;lt;category&amp;gt; analysis."&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If Code Is Successfully Generated:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return a JSON payload with:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;Entire Python code, escaped for valid JSON format&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code Escaping:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the &lt;code&gt;message&lt;/code&gt; field is a valid JSON string:

&lt;ul&gt;
&lt;li&gt;Escape all special characters, including newlines (&lt;code&gt;\n&lt;/code&gt;) and quotes (&lt;code&gt;\"&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;json.dumps()&lt;/code&gt; in Python or equivalent methods to serialize the code as a JSON-compatible string.&lt;/li&gt;
&lt;li&gt;Avoid using multi-line string blocks (&lt;code&gt;"""&lt;/code&gt;) in the JSON output.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Additional Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not include any explanatory text, comments, or preambles in the response.&lt;/li&gt;
&lt;li&gt;Avoid any prefixes like "Here's the code" or suffixes explaining the output.&lt;/li&gt;
&lt;li&gt;Only output the final JSON payload.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Code Requirements&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Input Handling:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accept a CSV file as a parameter in the &lt;code&gt;main()&lt;/code&gt; function. The parameter must be named &lt;code&gt;{CSV_FILE_PATH}&lt;/code&gt; and dynamically passed when calling the function.&lt;/li&gt;
&lt;li&gt;Validate the &lt;code&gt;csv_file&lt;/code&gt; parameter:

&lt;ul&gt;
&lt;li&gt;Check if &lt;code&gt;csv_file&lt;/code&gt; is a non-empty string.&lt;/li&gt;
&lt;li&gt;Check if the file exists and is readable before proceeding with analysis.&lt;/li&gt;
&lt;li&gt;Raise a clear error (e.g., &lt;code&gt;FileNotFoundError&lt;/code&gt;) if the file does not exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No &lt;code&gt;if __name__ == ' __main__':&lt;/code&gt; Block:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not include the &lt;code&gt;if __name__ == ' __main__':&lt;/code&gt; block in the generated code.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Output Restrictions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not include any &lt;code&gt;print()&lt;/code&gt; statements in the generated code.&lt;/li&gt;
&lt;li&gt;Return results exclusively via the &lt;code&gt;main()&lt;/code&gt; function, as a Python dictionary.&lt;/li&gt;
&lt;li&gt;Avoid any direct output, logging, or side effects.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Invoke &lt;code&gt;main&lt;/code&gt; at the End of the Script:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the script includes a call to &lt;code&gt;main("{CSV_FILE_PATH}")&lt;/code&gt; at the end, passing the &lt;code&gt;{CSV_FILE_PATH}&lt;/code&gt; placeholder dynamically.&lt;/li&gt;
&lt;li&gt;Replace &lt;code&gt;{CSV_FILE_PATH}&lt;/code&gt; with the actual file path during runtime.&lt;/li&gt;
&lt;li&gt;Do not print or log the results in the script.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Output Example for the Generated Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
       &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;csv_file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;No file provided&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_file&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;File not found: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;csv_file&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="c1"&gt;# Load and analyze the file
&lt;/span&gt;           &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;csv_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
           &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
               &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Empty CSV file&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="c1"&gt;# Perform analysis
&lt;/span&gt;           &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;File processed successfully&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;results&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;results&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
       &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
           &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;error&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

   &lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{CSV_FILE_PATH}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Dynamic Analysis&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically analyze the column names and sample data to:&lt;/li&gt;
&lt;li&gt;Infer field types (e.g., numeric, categorical, boolean)&lt;/li&gt;
&lt;li&gt;Determine the relevance of fields for analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Field Validation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamically categorize fields into:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Demographic Analysis:&lt;/strong&gt; Fields describing age, gender, or geographic distribution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Behavioral Analysis:&lt;/strong&gt; Fields related to customer behavior, such as frequency, purchase history, or subscriptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purchase Patterns:&lt;/strong&gt; Fields related to purchase amounts, categories, or discounts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product Preferences:&lt;/strong&gt; Fields describing product details, such as size, color, and seasonality.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Analysis:&lt;/strong&gt; Fields indicating customer feedback, such as ratings or reviews.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Field Identification:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implement logic to identify and classify fields dynamically based on:

&lt;ul&gt;
&lt;li&gt;Substring matches (e.g., &lt;code&gt;AgeGroup&lt;/code&gt; → Age, &lt;code&gt;Region&lt;/code&gt; → Location).&lt;/li&gt;
&lt;li&gt;Value patterns (e.g., numerical, categorical, boolean).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Modular Analysis:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Perform analysis for each identified category.&lt;/li&gt;
&lt;li&gt;Skip categories where no relevant fields can be inferred.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return results in JSON-compatible format, structured as:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"summary_statistics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"segmentation_results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"behavioral_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"purchase_patterns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"product_preferences"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"visualizations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Escape Code in JSON Output:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Python script should be included in the &lt;code&gt;message&lt;/code&gt; field as a single JSON-compatible string, with all newlines (&lt;code&gt;\n&lt;/code&gt;) and special characters escaped.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Below is the generated code from one of the recent prompts:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;import pandas as pd&lt;br&gt;
import json&lt;br&gt;
from typing import Dict, Any&lt;br&gt;
import numpy as np&lt;/p&gt;

&lt;p&gt;def categorize_fields(df):&lt;br&gt;
    categories = {&lt;br&gt;
        'demographic': [],&lt;br&gt;
        'behavioral': [],&lt;br&gt;
        'purchase': [],&lt;br&gt;
        'response': []&lt;br&gt;
    }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for column in df.columns:
    col_lower = column.lower()
    if any(term in col_lower for term in ['age', 'gender', 'region']):
        categories['demographic'].append(column)
    elif any(term in col_lower for term in ['frequency', 'membership', 'preferred']):
        categories['behavioral'].append(column)
    elif any(term in col_lower for term in ['purchase', 'promo', 'value']):
        categories['purchase'].append(column)
    elif any(term in col_lower for term in ['review', 'score', 'rating']):
        categories['response'].append(column)

return categories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def analyze_demographics(df, demographic_fields):&lt;br&gt;
    results = {}&lt;br&gt;
    for field in demographic_fields:&lt;br&gt;
        results[field] = df[field].value_counts().to_dict()&lt;br&gt;
    return results&lt;/p&gt;

&lt;p&gt;def analyze_behavioral(df, behavioral_fields):&lt;br&gt;
    results = {}&lt;br&gt;
    for field in behavioral_fields:&lt;br&gt;
        results[field] = df[field].value_counts().to_dict()&lt;br&gt;
    return results&lt;/p&gt;

&lt;p&gt;def analyze_purchases(df, purchase_fields):&lt;br&gt;
    results = {}&lt;br&gt;
    numeric_fields = df[purchase_fields].select_dtypes(include=[np.number]).columns&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for field in numeric_fields:
    results[field] = {
        'mean': float(df[field].mean()),
        'median': float(df[field].median()),
        'std': float(df[field].std())
    }

categorical_fields = list(set(purchase_fields) - set(numeric_fields))
for field in categorical_fields:
    results[field] = df[field].value_counts().to_dict()

return results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def analyze_response(df, response_fields):&lt;br&gt;
    results = {}&lt;br&gt;
    for field in response_fields:&lt;br&gt;
        if df[field].dtype in [np.float64, np.int64]:&lt;br&gt;
            results[field] = {&lt;br&gt;
                'mean': float(df[field].mean()),&lt;br&gt;
                'median': float(df[field].median())&lt;br&gt;
            }&lt;br&gt;
        else:&lt;br&gt;
            results[field] = df[field].value_counts().to_dict()&lt;br&gt;
    return results&lt;/p&gt;

&lt;p&gt;def main(csv_file: str) -&amp;gt; Dict[str, Any]:&lt;br&gt;
    try:&lt;br&gt;
        df = pd.read_csv(csv_file)&lt;br&gt;
        categories = categorize_fields(df)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    results = {
        'error': False,
        'results': {
            'demographic_analysis': analyze_demographics(df, categories['demographic']),
            'behavioral_analysis': analyze_behavioral(df, categories['behavioral']),
            'purchase_analysis': analyze_purchases(df, categories['purchase']),
            'response_analysis': analyze_response(df, categories['response'])
        }
    }

    return results

except Exception as e:
    return {
        'error': True,
        'message': f'Analysis failed: {str(e)}'
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;results = main('shopping_behavior_test.csv')&lt;br&gt;
print(json.dumps(results, indent=2))&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
#### Send JSON to Claude for Python code generation

Below is the code that executes the generated Python code and then makes things compatible with Python data types:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  To execute generated Python code
&lt;/h1&gt;

&lt;p&gt;def execute_runtime_code(generated_code):&lt;br&gt;
    try:&lt;br&gt;
        sandbox_namespace = {}&lt;br&gt;
        # Execute the generated code in the sandboxed namespace&lt;br&gt;
        exec(generated_code, sandbox_namespace)&lt;br&gt;
        if "main" not in sandbox_namespace:&lt;br&gt;
            return {&lt;br&gt;
                "error": True,&lt;br&gt;
                "message": "main function not found",&lt;br&gt;
                "results": None&lt;br&gt;
            }&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if "results" in sandbox_namespace:
        return {
            "error": False,
            "message": "Execution completed successfully.",
            "results": sandbox_namespace["results"]
        }
    else:
        return {
            "error": True,
            "message": "No 'results' variable found in the generated script.",
            "results": None
        }
except Exception as e:
    return {
        "error": True,
        "message": f"An error occurred during execution: {str(e)}",
        "results": None
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Casting numpy datatypes to Python built-in types
&lt;/h1&gt;

&lt;p&gt;def convert_to_serializable(obj):&lt;br&gt;
    if isinstance(obj, dict):&lt;br&gt;
        return {k: convert_to_serializable(v) for k, v in obj.items()}&lt;br&gt;
    elif isinstance(obj, list):&lt;br&gt;
        return [convert_to_serializable(item) for item in obj]&lt;br&gt;
    elif isinstance(obj, np.integer):&lt;br&gt;
        return int(obj)&lt;br&gt;
    elif isinstance(obj, np.floating):&lt;br&gt;
        return float(obj)&lt;br&gt;
    elif isinstance(obj, np.ndarray):&lt;br&gt;
        return obj.tolist()&lt;br&gt;
    return obj&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Alright. The next step was to access this generated data in JavaScript and show both charts and stats on the webpage.

#### Execute Python to create JSON structure.

The plan was to send the Python-generated JSON output via an AJAX request and access it in the JavaScript code. However, this approach failed because, while the parent JSON fields remained consistent, the inner fields varied. Hard-coding the JavaScript wasn’t feasible, as files with different schemas caused errors for undefined fields. The solution? Create a new prompt that generates both HTML and JavaScript by inferring the JSON structure produced by the Python code.

#### For Dashboard’s JavaScript and HTML Generation

The very first prompt was:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are a front-end developer tasked with creating dynamic dashboards based on JSON data. The JSON data includes fixed top-level categories but variable inner keys. The JSON Data is given below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;DASHBOARD_JSON&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTML Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only the relevant sections of the HTML (not the entire &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; page).&lt;/li&gt;
&lt;li&gt;Use Bootstrap for layout and styling.&lt;/li&gt;
&lt;li&gt;Include summary cards for key metrics.&lt;/li&gt;
&lt;li&gt;Each card must have a &lt;strong&gt;dynamic &lt;code&gt;id&lt;/code&gt;&lt;/strong&gt; for future updates.&lt;/li&gt;
&lt;li&gt;Dynamically generate &lt;strong&gt;chart containers&lt;/strong&gt; for data visualization.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JavaScript Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write JavaScript using &lt;strong&gt;jQuery&lt;/strong&gt; to:

&lt;ul&gt;
&lt;li&gt;Dynamically populate the summary cards.&lt;/li&gt;
&lt;li&gt;Generate charts based on the JSON data.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Assume that the JSON data will be provided as a variable named &lt;code&gt;{DASHBOARD_JSON}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Focus on generating dynamic JS for &lt;code&gt;demographic_analysis&lt;/code&gt;, &lt;code&gt;behavioral_analysis&lt;/code&gt;, &lt;code&gt;purchase_analysis&lt;/code&gt;, and &lt;code&gt;response_analysis&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Output Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Output a JSON object with two fields:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;html&lt;/code&gt;: The Bootstrap-compatible HTML structure as a JSON string.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;javascript&lt;/code&gt;: The jQuery code to dynamically update the dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JSON Input Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Execution completed successfully."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"demographic_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"age_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;44.06&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"median"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;44.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.2&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"gender_distribution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Male"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2652&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Female"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1248&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"behavioral_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subscription_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.27&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"purchase_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"amount_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;59.76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;233081&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"response_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"rating_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.75&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTML Section Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row mb-5"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"demographic-analysis"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card text-white bg-primary mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Average Age&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"avg-age"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0.00&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Expected Output Format:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;section class='row mb-5' id='demographic-analysis'&amp;gt; ... &amp;lt;/section&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"javascript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$('#avg-age').text({DASHBOARD_JSON}.results.results.demographic_analysis.age_stats.mean); ... // Full JS code"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Output Strictness:&lt;/strong&gt;
Do not include any preamble or suffix like "Here's the solution" or "I'll help you with this."
The response must contain only the final JSON payload, nothing else.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This prompt accepts the JSON structure generated by the generated code( _yeah kind of “inception” you know_).

Another thing it was doing to produce the generated output of both HTML and JS in JSON format:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Expected Output Format:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;section class='row mb-5' id='demographic-analysis'&amp;gt; ... &amp;lt;/section&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"javascript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$('#avg-age').text({DASHBOARD_JSON}.results.results.demographic_analysis.age_stats.mean); ... // Full JS code"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
It didn’t work due to encoding and escaping issues with the JSON. I decided to return the data in XML format instead. It was cleaner too. Below is one version of the dashboard prompt:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You are a front-end developer tasked with creating dynamic dashboards based on JSON data. The JSON data includes fixed top-level categories but variable inner keys. The JSON Data is given below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;DASHBOARD_JSON&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;HTML Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only the relevant sections of the HTML (not the entire &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; page).&lt;/li&gt;
&lt;li&gt;Use Bootstrap for layout and styling.&lt;/li&gt;
&lt;li&gt;Include summary cards for key metrics.&lt;/li&gt;
&lt;li&gt;Each card must have a &lt;strong&gt;dynamic &lt;code&gt;id&lt;/code&gt;&lt;/strong&gt; for future updates.&lt;/li&gt;
&lt;li&gt;Dynamically generate &lt;strong&gt;chart containers&lt;/strong&gt; for data visualization.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JavaScript Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write JavaScript using &lt;strong&gt;jQuery&lt;/strong&gt; to:
&lt;strong&gt;Variable Declaration:&lt;/strong&gt;
    - Define a variable rawData containing the JSON string from {DASHBOARD_JSON}.
    - Ensure &lt;code&gt;rawData&lt;/code&gt; is a properly escaped and valid JSON string for use in JavaScript.
&lt;strong&gt;Parsing Logic&lt;/strong&gt;
    - Parse &lt;code&gt;rawData&lt;/code&gt; into a JavaScript object using &lt;code&gt;JSON.parse&lt;/code&gt;.
&lt;strong&gt;Function Definition:&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create a function named &lt;code&gt;generateDashboard&lt;/code&gt; that accepts a single parameter &lt;code&gt;dashboardData&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;The function must:

&lt;ul&gt;
&lt;li&gt;Dynamically populate summary cards.&lt;/li&gt;
&lt;li&gt;Dynamically generate charts based on the data in &lt;code&gt;dashboardData&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Function Invocation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Define a variable &lt;code&gt;rawData&lt;/code&gt; containing the JSON string from &lt;code&gt;{DASHBOARD_JSON}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Code Structure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not include &lt;code&gt;$(document).ready&lt;/code&gt; in the generated code.&lt;/li&gt;
&lt;li&gt;Only provide:

&lt;ol&gt;
&lt;li&gt;The function definition for &lt;code&gt;generateDashboard&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The variable &lt;code&gt;rawData&lt;/code&gt; with &lt;code&gt;{DASHBOARD_JSON}&lt;/code&gt; as the placeholder.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;JSON.parse&lt;/code&gt; logic.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;generateDashboard&lt;/code&gt; function call.&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;Dynamic Logic:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assume the input JSON follows this structure:
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"demographic_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"behavioral_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"purchase_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"response_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;




&lt;/li&gt;

&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;dashboardData.results&lt;/code&gt; as the base for extracting and visualizing data.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Output Requirements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate an XML response with the following format:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;dashboard&amp;gt;&lt;/code&gt;: Root element containing:&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt;: Encapsulates the HTML structure needed to display the dashboard.

&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;&amp;lt;![CDATA[]]&amp;gt;&lt;/code&gt; section for HTML content.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;javascript&amp;gt;&lt;/code&gt;: Encapsulates the JavaScript code required to populate and render the dashboard.

&lt;ul&gt;
&lt;li&gt;Use a &lt;code&gt;&amp;lt;![CDATA[]]&amp;gt;&lt;/code&gt; section for JavaScript content.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Avoid any prefixes, suffixes, or extra text outside the XML structure. Ensure the generated XML is valid and can be directly parsed.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JSON Input Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Execution completed successfully."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"results"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"demographic_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"age_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;44.06&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"median"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;44.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"std"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;15.2&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"gender_distribution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Male"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2652&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"Female"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1248&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"behavioral_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subscription_rate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.27&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"purchase_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"amount_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;59.76&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;233081&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"response_analysis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"rating_stats"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mean"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;3.75&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;HTML Summary Card Example:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"margin-top:20px;"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-12"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="c"&gt;&amp;lt;!-- Summary Section --&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;section&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"row mb-5"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card text-white bg-primary mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Average Purchase Amount&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"average-purchase-amount"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;$0.00&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card text-white bg-success mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Total Revenue&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"total-revenue"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;$0.00&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"col-md-4"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card text-white bg-warning mb-3"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-body"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                            &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Subscription Rate&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                           &lt;span class="nt"&gt;&amp;lt;p&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"card-text"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"subscription-rate"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;0%&lt;span class="nt"&gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;HTML Charts Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;section&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
                &lt;span class="nc"&gt;.chart-container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Center horizontally */&lt;/span&gt;
                    &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* Center vertically (if needed) */&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nc"&gt;.charthing&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;400px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt; &lt;span class="cp"&gt;!important&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
                &lt;span class="c"&gt;&amp;lt;!-- Age Distribution Chart --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;div&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;h5&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Age Distribution&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                        &lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"charthing"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"ageDistributionChart"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"800"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"400"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: block; box-sizing: border-box; height: 200px; width: 400px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

                &lt;span class="c"&gt;&amp;lt;!-- Gender Distribution Chart --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;h5&amp;gt;&lt;/span&gt;Gender Distribution&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"charthing"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"genderDistributionChart"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: block; box-sizing: border-box; height: 300px; width: 300px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

                &lt;span class="c"&gt;&amp;lt;!-- Color Preferences Chart --&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"chart-container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;h5&amp;gt;&lt;/span&gt;Color Preferences&lt;span class="nt"&gt;&amp;lt;/h5&amp;gt;&lt;/span&gt;
                    &lt;span class="nt"&gt;&amp;lt;canvas&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"charthing"&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"colorPreferencesChart"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"1200"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"600"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: block; box-sizing: border-box; height: 300px; width: 600px;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/canvas&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/section&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Expected Output Format:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"html"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;section class='row mb-5' id='demographic-analysis'&amp;gt; ... &amp;lt;/section&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"javascript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"$('#avg-age').text({DASHBOARD_JSON}.results.results.demographic_analysis.age_stats.mean); ... // Full JS code"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Output Strictness:&lt;/strong&gt;
Do not include any preamble or suffix like "Here's the solution" or "I'll help you with this."
The response must contain only the final JSON payload, nothing else.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
It almost worked but there was a glitch. In the section that was responsible for generating JS code, somehow it was not assigning the returned JSON for the dashboard itself in a variable:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JavaScript Code:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Write JavaScript using &lt;strong&gt;jQuery&lt;/strong&gt; to:
&lt;strong&gt;Variable Declaration:&lt;/strong&gt;
    - Define a variable rawData containing the JSON string from {DASHBOARD_JSON}.
    - Ensure &lt;code&gt;rawData&lt;/code&gt; is a properly escaped and valid JSON string for use in JavaScript.
&lt;strong&gt;Parsing Logic&lt;/strong&gt;
    - Parse &lt;code&gt;rawData&lt;/code&gt; into a JavaScript object using &lt;code&gt;JSON.parse&lt;/code&gt;.
&lt;strong&gt;Function Definition:&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create a function named &lt;code&gt;generateDashboard&lt;/code&gt; that accepts a single parameter &lt;code&gt;dashboardData&lt;/code&gt;.

&lt;ul&gt;
&lt;li&gt;The function must:

&lt;ul&gt;
&lt;li&gt;Dynamically populate summary cards.&lt;/li&gt;
&lt;li&gt;Dynamically generate charts based on the data in &lt;code&gt;dashboardData&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
It took a few iterations to come up with an output like the one below:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;br&gt;
&lt;br&gt;
    &lt;br&gt;
&amp;lt;![CDATA[&lt;/p&gt;


    
    
        
            
                
                    &lt;h5&gt;Average Age&lt;/h5&gt;
                    &lt;p id="avg-age"&gt;0&lt;/p&gt;
                
            
        
        
            
127.0.0.1 - - [15/Jan/2025 09:50:07] "POST /upload HTTP/1.1" 200 -
                
                    &lt;h5&gt;Total Sales&lt;/h5&gt;
                    &lt;p id="total-sales"&gt;$0&lt;/p&gt;
                
            
        
        
            
                
                    &lt;h5&gt;Average Rating&lt;/h5&gt;
                    &lt;p id="avg-rating"&gt;0&lt;/p&gt;
                
            
        
        
            
                
                    &lt;h5&gt;Subscription Rate&lt;/h5&gt;
                    &lt;p id="sub-rate"&gt;0%&lt;/p&gt;
                
            
        
    

    
    
        
            
                
                    &lt;h5&gt;Gender Distribution&lt;/h5&gt;
                    
                
            
        
        
            
                
                    &lt;h5&gt;Size Distribution&lt;/h5&gt;
                    
                
            
        
    

    
        
            
                
                    &lt;h5&gt;Category Distribution&lt;/h5&gt;
                    
                
            
        
        
            
                
                    &lt;h5&gt;Seasonal Preferences&lt;/h5&gt;
                    
                
            
        
    


&lt;p&gt;]]&amp;gt;&lt;br&gt;
    &lt;br&gt;
    &lt;br&gt;
&amp;lt;![CDATA[&lt;br&gt;
const rawData = &lt;code&gt;{"error":false,"message":"Execution completed successfully.","results":{"error":false,"results":{"demographic_analysis":{"age_stats":{"mean":44.06846153846154,"median":44.0,"std":15.207589127162382},"gender_distribution":{"Male":2652,"Female":1248},"location_distribution":{"Montana":96,"California":95,"Idaho":93,"Illinois":92,"Alabama":89,"Minnesota":88,"Nebraska":87,"New York":87,"Nevada":87,"Maryland":86,"Delaware":86,"Vermont":85,"Louisiana":84,"North Dakota":83,"Missouri":81,"West Virginia":81,"New Mexico":81,"Mississippi":80,"Indiana":79,"Georgia":79,"Kentucky":79,"Arkansas":79,"North Carolina":78,"Connecticut":78,"Virginia":77,"Ohio":77,"Tennessee":77,"Texas":77,"Maine":77,"South Carolina":76,"Colorado":75,"Oklahoma":75,"Wisconsin":75,"Oregon":74,"Pennsylvania":74,"Washington":73,"Michigan":73,"Alaska":72,"Massachusetts":72,"Wyoming":71,"Utah":71,"New Hampshire":71,"South Dakota":70,"Iowa":69,"Florida":68,"New Jersey":67,"Hawaii":65,"Arizona":65,"Kansas":63,"Rhode Island":63}},"purchase_patterns":{"amount_stats":{"mean":59.76435897435898,"median":60.0,"total":233081},"category_distribution":{"Clothing":1737,"Accessories":1240,"Footwear":599,"Outerwear":324},"discount_usage":0.43,"promo_usage":0.43},"product_preferences":{"size_distribution":{"M":1755,"L":1053,"S":663,"XL":429},"color_preferences":{"Olive":177,"Yellow":174,"Silver":173,"Teal":172,"Green":169,"Black":167,"Cyan":166,"Violet":166,"Gray":159,"Maroon":158,"Orange":154,"Charcoal":153,"Pink":153,"Magenta":152,"Blue":152,"Purple":151,"Peach":149,"Red":148,"Beige":147,"Indigo":147,"Lavender":147,"Turquoise":145,"White":142,"Brown":141,"Gold":138},"seasonal_preferences":{"Spring":999,"Fall":975,"Winter":971,"Summer":955},"item_popularity":{"Blouse":171,"Jewelry":171,"Pants":171,"Shirt":169,"Dress":166,"Sweater":164,"Jacket":163,"Belt":161,"Sunglasses":161,"Coat":161,"Sandals":160,"Socks":159,"Skirt":158,"Shorts":157,"Scarf":157,"Hat":154,"Handbag":153,"Hoodie":151,"Shoes":150,"T-shirt":147,"Sneakers":145,"Boots":144,"Backpack":143,"Gloves":140,"Jeans":124}},"customer_behavior":{"avg_review_rating":3.7499487179487176,"subscription_rate":0.27,"shipping_preferences":{"Free Shipping":675,"Standard":654,"Store Pickup":650,"Next Day Air":648,"Express":646,"2-Day Shipping":627},"payment_methods":{"PayPal":677,"Credit Card":671,"Cash":670,"Debit Card":636,"Venmo":634,"Bank Transfer":612},"purchase_frequency":{"Every 3 Months":584,"Annually":572,"Quarterly":563,"Monthly":553,"Bi-Weekly":547,"Fortnightly":542,"Weekly":539},"avg_previous_purchases":25.35153846153846}}}}&lt;/code&gt;;&lt;/p&gt;

&lt;p&gt;const dashboardData = JSON.parse(rawData);&lt;br&gt;
const data = dashboardData.results.results;&lt;/p&gt;

&lt;p&gt;function generateDashboard(data) {&lt;br&gt;
    // Update Summary Cards&lt;br&gt;
    $('#avg-age').text(data.demographic_analysis.age_stats.mean.toFixed(2));&lt;br&gt;
    $('#total-sales').text(&lt;code&gt;$${data.purchase_patterns.amount_stats.total.toLocaleString()}&lt;/code&gt;);&lt;br&gt;
    $('#avg-rating').text(data.customer_behavior.avg_review_rating.toFixed(2));&lt;br&gt;
    $('#sub-rate').text(&lt;code&gt;${(data.customer_behavior.subscription_rate * 100).toFixed(1)}%&lt;/code&gt;);&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Gender Distribution Chart
new Chart(document.getElementById('genderChart'), {
    type: 'pie',
    data: {
        labels: Object.keys(data.demographic_analysis.gender_distribution),
        datasets: [{
            data: Object.values(data.demographic_analysis.gender_distribution),
            backgroundColor: ['#36A2EB', '#FF6384']
        }]
    }
});

// Size Distribution Chart
new Chart(document.getElementById('sizeChart'), {
    type: 'bar',
    data: {
        labels: Object.keys(data.product_preferences.size_distribution),
        datasets: [{
            label: 'Size Distribution',
            data: Object.values(data.product_preferences.size_distribution),
            backgroundColor: '#4BC0C0'
        }]
    }
});

// Category Distribution Chart
new Chart(document.getElementById('categoryChart'), {
    type: 'bar',
    data: {
        labels: Object.keys(data.purchase_patterns.category_distribution),
        datasets: [{
            label: 'Category Distribution',
            data: Object.values(data.purchase_patterns.category_distribution),
            backgroundColor: '#FFCE56'
        }]
    }
});

// Seasonal Preferences Chart
new Chart(document.getElementById('seasonalChart'), {
    type: 'bar',
    data: {
        labels: Object.keys(data.product_preferences.seasonal_preferences),
        datasets: [{
            label: 'Seasonal Preferences',
            data: Object.values(data.product_preferences.seasonal_preferences),
            backgroundColor: '#FF9F40'
        }]
    }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;generateDashboard(data);&lt;br&gt;
]]&amp;gt;&lt;br&gt;
    &lt;br&gt;
&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
As you can see, the rawData variable holds the JSON output generated by the Python code. It produces summary cards and charts by inferring the structure of the incoming JSON. The entire HTML and JS code is generated based on the inference of the JSON output from the Python code.

![](https://cdn-images-1.medium.com/max/774/0*bCxFroiqPAAB_Uua.png)

#### One more thing

No, no, I’m not trying to [imitate](https://www.youtube.com/watch?v=in9SX3enCHU) Steve Jobs. When I was preparing the demo for this project, I initially planned to create a CSV file unrelated to behavior analysis just for testing. I uploaded the file, and to my surprise, Claude accepted it and generated the damn code.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A,B,C&lt;br&gt;
LOL,LOL,LOL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Obviously, the generated JS code didn’t work at all. The code produced a dictionary like this:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;{&lt;br&gt;
  'error': False,&lt;br&gt;
  'message': 'Execution completed successfully.',&lt;br&gt;
  'results': {&lt;br&gt;
    'error': True,&lt;br&gt;
    'results': {&lt;br&gt;
.......&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
So, while the error inside the results was correctly returning True with the relevant text in the message field, the outer error was still False. This was happening due to the following code:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;results = sandbox_namespace['results']&lt;br&gt;
            if results['error']:&lt;br&gt;
                return {&lt;br&gt;
                    "error": True,&lt;br&gt;
                    "message": "Execution failed",&lt;br&gt;
                    "results": sandbox_namespace["results"]&lt;br&gt;
                }&lt;br&gt;
            else:&lt;br&gt;
                return {&lt;br&gt;
                    "error": False,&lt;br&gt;
                    "message": "Execution completed successfully.",&lt;br&gt;
                    "results": sandbox_namespace["results"]&lt;br&gt;
                }&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
As you can see I was only testing the existence of results key only. I fixed it by doing the following:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;results = sandbox_namespace['results']&lt;br&gt;
            if results['error']:&lt;br&gt;
                return {&lt;br&gt;
                    "error": True,&lt;br&gt;
                    "message": "Execution failed",&lt;br&gt;
                    "results": sandbox_namespace["results"]&lt;br&gt;
                }&lt;br&gt;
            else:&lt;br&gt;
                return {&lt;br&gt;
                    "error": False,&lt;br&gt;
                    "message": "Execution completed successfully.",&lt;br&gt;
                    "results": sandbox_namespace["results"]&lt;br&gt;
                }&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
OK, this was fixed, but I also need to make changes on the JS side in the index.html file.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if(response.error) {&lt;br&gt;
                        console.log(response.message)&lt;br&gt;
                        $("#errorMessage").show()&lt;br&gt;
                        $("#errorMessage").html(&lt;code&gt;&amp;lt;div class="alert alert-danger"&amp;gt;${response.message}&amp;lt;/div&amp;gt;&lt;/code&gt;)&lt;br&gt;
                        $("#wait").hide()&lt;br&gt;
                        return true&lt;br&gt;
                       }&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
OK everything was fine but then I started getting the error:

Uncaught SyntaxError: Identifier 'rawData' has already been declared

Somehow, the rawData variable reference was being retained. I tried the following, but it still didn't work:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;$("#runtimeJs").remove()&lt;br&gt;
// Dynamically execute the JavaScript&lt;br&gt;
const script = document.createElement('script')&lt;br&gt;
script.id = "runtimeJs"&lt;br&gt;
script.type = 'text/javascript'&lt;br&gt;
script.text = jsContent&lt;br&gt;
document.body.appendChild(script);&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The relevant prompt section was:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JavaScript Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Write JavaScript using &lt;strong&gt;jQuery&lt;/strong&gt; to:&lt;br&gt;
&lt;strong&gt;Variable Declaration:&lt;/strong&gt;&lt;br&gt;
    - Define a variable rawData containing the JSON string from {DASHBOARD_JSON}.&lt;br&gt;
    Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```javascript
const rawData = `{DASHBOARD_JSON}`;
```
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Ensure `rawData` is a properly escaped and valid JSON string for use in JavaScript.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Parsing Logic&lt;/strong&gt;&lt;br&gt;
    - Parse the JSON string into a JavaScript object using JSON.parse&lt;br&gt;
    Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```javascript
    const dashboardData = JSON.parse(rawData);
```
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Extract the main data object for rendering charts and cards:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dashboardData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
First, it was declared as const, preventing the removal of existing references. The final changes are:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;JavaScript Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Write JavaScript using &lt;strong&gt;jQuery&lt;/strong&gt; to:&lt;br&gt;
&lt;strong&gt;Variable Cleanup (Before Declaration)&lt;/strong&gt;&lt;br&gt;
    - Ensure &lt;code&gt;rawData&lt;/code&gt; is removed before defining it again.&lt;br&gt;
    - Ensure &lt;code&gt;dashboardData&lt;/code&gt; is removed before defining it again.&lt;br&gt;
    Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```javascript
 delete window.rawData
 delete window.dashboardData
```
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;strong&gt;Variable Declaration:&lt;/strong&gt;&lt;br&gt;
    - Define a variable &lt;code&gt;rawData&lt;/code&gt; using &lt;code&gt;var&lt;/code&gt; (instead of &lt;code&gt;const&lt;/code&gt;) to avoid redeclaration errors.&lt;br&gt;
    Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```javascript
var rawData = `{DASHBOARD_JSON}`;
```
&lt;/code&gt;&lt;/pre&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Ensure `rawData` is a properly escaped and valid JSON string for use in JavaScript.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Parsing Logic&lt;/strong&gt;&lt;br&gt;
    - Parse the JSON string into a JavaScript object using JSON.parse&lt;br&gt;
    Example:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;```javascript
    var dashboardData = JSON.parse(rawData);
```
&lt;/code&gt;&lt;/pre&gt;


&lt;ul&gt;
&lt;li&gt;Extract the main data object for rendering charts and cards:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dashboardData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Now, it generated the JS code as follows:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// Clean up existing variables&lt;br&gt;
delete window.rawData;&lt;br&gt;
delete window.dashboardData;&lt;/p&gt;

&lt;p&gt;// Define raw data&lt;br&gt;
var rawData = &lt;code&gt;....&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
As you can see, the generated code now clears all context related to both rawData and dashboardData from the existing browser window. To be on the safe side, I added the following before injecting and executing the runtime JS code in the current window:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;// Cleaning previous JS execution&lt;br&gt;
                        // Remove existing one&lt;br&gt;
                        $("#runtimeJs").remove()&lt;br&gt;
                        window.rawData = undefined&lt;br&gt;
                        delete window.rawData&lt;br&gt;
                        window.dashboardData = undefined&lt;br&gt;
                        delete window.dashboardData&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    if (window.Chart) {
                        Chart.helpers.each(Chart.instances, function(instance) {
                            instance.destroy();
                        });
                    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;.....&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Now it was removing all existing traces of both variables before injecting and executing the incoming JS code.

And while I was running the final tests, the app suddenly stopped working. I then received the following email:

![](https://cdn-images-1.medium.com/max/1024/0*WkAS2aTF2fZtX_W_.png)

Ouch! My entire $5 free credit evaporated. I had to purchase credits just to run the demo.

### Conclusion

Alright, so you saw how amazing and powerful Claude is to perform such kinds of tasks. Claude is not only good at code generation but also at performing data analysis. I don’t know whether you got excited similar to how I was while working on this project, but I’d definitely tell you that it took hours and multiple sessions over days to make it happen. I have not covered all the “toy scripts” I had written for different components of this project, as it would make this post unnecessarily lengthy, and you could have gotten bored. However, I will be putting all prompt iterations in a separate folder for your learning. Hope you’ll enjoy it. Like always, the code is available on [GitHub](https://github.com/kadnan/Adaptive-Customer-Behavior-Analysis-Dashboard).

_Looking to create something similar or even more exciting?_ [_Schedule_](https://calendly.com/kadnan/one_one_15min) _a meeting or email me at_ **_kadnan @ gmail.com._**

**Love What You’re Learning Here?**  
_If my posts have sparked ideas or saved you time, consider_ [_supporting_](https://adnansiddiqi.me/donate.html) _my journey of learning and sharing. Even a small contribution helps me keep this blog alive and thriving._

_Originally published at_ [_https://blog.adnansiddiqi.me_](https://blog.adnansiddiqi.me/create-an-adaptive-customer-behavior-analytics-dashboard-with-claude-ai-and-python/) _on January 30, 2025._

* * *
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>dataanalyticsdashboa</category>
      <category>claude</category>
      <category>genai</category>
      <category>behavioranalysis</category>
    </item>
    <item>
      <title>Illness Is a Form of Meditation</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Fri, 17 Jan 2025 10:30:15 +0000</pubDate>
      <link>https://dev.to/kadnan/illness-is-a-form-of-meditation-5dpo</link>
      <guid>https://dev.to/kadnan/illness-is-a-form-of-meditation-5dpo</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbywh7xiruguzhrysmd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhbywh7xiruguzhrysmd5.png" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;PC: ChatGPT&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Last night, I started feeling unwell during a company meeting. As the meeting progressed, I felt cold and began shivering. By the time it ended, the shivering had intensified. Even with socks on, I couldn’t warm up. I went to bed around 2 a.m. but had to get up multiple times to use the bathroom. I didn’t want to disturb my wife, but eventually, I needed medicine. She gave me Panadol and some biscuits, which I ate before taking the medicine. After that, I finally slept.&lt;/p&gt;

&lt;p&gt;In the morning, I still felt weak, though I didn’t have a fever. After breakfast, I remained in bed, lacking the energy to do anything. I asked my son to bring me some books and started reading. I also finished a long podcast featuring an interview with the &lt;a href="https://www.youtube.com/watch?v=ugvHCXCOmm4" rel="noopener noreferrer"&gt;Anthropic CEO&lt;/a&gt;, which I had been listening to in chunks during my commutes.&lt;/p&gt;

&lt;p&gt;Strangely, despite feeling unwell, I experienced a sense of calm and presence. It felt as if I had already achieved whatever I wanted in life and no longer needed to strive for anything. My entire purpose seemed to be reading books and listening to podcasts. My mind was quiet, like, it wasn’t juggling multiple tasks or thoughts at once. You know how a CPU makes noise when too many processes are running and becomes silent when those processes are killed? The same thing happened to my mind. The strange part was that even when I tried to think about my goals, they didn’t bother me; they simply vanished. Maybe I had accepted that I was ill and didn’t have the stamina to do anything. I don’t know. The feeling of this &lt;em&gt;surrender&lt;/em&gt; was amazing&lt;/p&gt;

&lt;p&gt;I watched and appreciated how my wife managed multiple tasks; giving me medicine and food like chopped carrots and mutton &lt;em&gt;yakhni&lt;/em&gt; (gravy), measuring my mom’s blood pressure and sugar levels, cooking, and keeping an eye on whether our elder son was studying. I had no words, only appreciation for her.&lt;/p&gt;

&lt;p&gt;After lunch, I offered &lt;em&gt;Zohar&lt;/em&gt; prayers, performing &lt;em&gt;Tayammum&lt;/em&gt; instead of &lt;em&gt;Wudu&lt;/em&gt; due to weakness. After praying, I felt a deep stillness, something I hadn’t experienced in years. I could hear the silence around me, a sensation I remember from childhood. As children, we live fully in the present, free from the weight of the past or future. That’s why we long for childhood; not just for the experiences, but for the simplicity of being present.&lt;/p&gt;

&lt;p&gt;Oh, besides that, another positive side of illness is that it allows you to do things you usually don’t or don’t do often, like reading and listening to podcasts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b8dr4ejs7qg5wzgs1e1.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0b8dr4ejs7qg5wzgs1e1.jpeg" width="768" height="1024"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This illness, in a way, became a form of meditation. It forced me to pause, both mentally and physically. I wasn’t chasing anything, just observing and appreciating what was around me. Sometimes, the best thing to do is nothing. Just as an overloaded computer heats up and slows down, our minds and bodies need rest to function well. When we constantly push ourselves, it takes a toll on both mental and physical health.&lt;/p&gt;

&lt;p&gt;Take a break. Appreciate what you have. Be thankful.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/illness-is-a-form-of-meditation/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on January 17, 2025.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>life</category>
      <category>calmness</category>
      <category>productivity</category>
      <category>mindfulness</category>
    </item>
    <item>
      <title>Introduction to prompt engineering</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Fri, 27 Sep 2024 05:00:25 +0000</pubDate>
      <link>https://dev.to/kadnan/introduction-to-prompt-engineering-2ig0</link>
      <guid>https://dev.to/kadnan/introduction-to-prompt-engineering-2ig0</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is part of the&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/tag/genai" rel="noopener noreferrer"&gt;&lt;em&gt;GenAI Series&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only way we can interact with an LLM model is by passing an instruction to retrieve a response. That instruction is called a prompt. In this post, we are going to discuss what a prompt is and what prompt engineering entails&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a Prompt
&lt;/h3&gt;

&lt;p&gt;A &lt;em&gt;prompt&lt;/em&gt; is simply the instruction or question you give to an AI or language model to get a response. Think of it as a way to guide the AI toward the answer or output you want. Imagine you’re talking to a super-smart friend who’s always eager to help but needs a little guidance on what you want. The prompt is how you start that conversation and steer it in the right direction. It could be as simple as asking, “What’s the weather like today?” or as complex as, “Write me a short story about a time-traveling chef.” Just like how you might phrase things differently depending on who you’re talking to, crafting a good prompt is about finding the right words to communicate clearly with AI, so it understands exactly what you’re after and can give you the best possible response..&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Prompt Engineering
&lt;/h3&gt;

&lt;p&gt;Prompt engineering is the art of crafting the perfect question or instruction to get the best possible answer from an AI. Think of it as learning how to be a really good coach or teacher for AI. You’re not just asking questions or giving instructions — you’re crafting them carefully to bring out the AI’s best performance. It’s like knowing exactly how to explain a task to a friend so they not only get it right but might even surprise you with how well they do it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components of a prompt
&lt;/h3&gt;

&lt;p&gt;The basic components of a prompt are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Instruction:&lt;/strong&gt; This is the main task you’re giving the AI. It’s like telling a friend what you need help with. Example: &lt;em&gt;Create a recipe for a vegetarian pasta dish.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context:&lt;/strong&gt; Any background info that helps the AI understand the situation better. Think of it as filling your friend in on what’s going on. Example: &lt;em&gt;I’m cooking for a dinner party where one guest is allergic to nuts.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; The specific information or data you’re giving the AI to work with. It’s the raw material for the task. Example: &lt;em&gt;I have tomatoes, spinach, garlic, and various pasta shapes in my pantry.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output format:&lt;/strong&gt; How you want the AI to present its answer. Like asking your friend to give their advice in bullet points or as a story. Example: &lt;em&gt;Present the recipe in a numbered list with ingredients followed by steps.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Examples (sometimes):&lt;/strong&gt; Showing the AI what you mean by giving it a sample. It’s like saying, “Here’s what I’m looking for.” Examples:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting it all together, a complete prompt might look like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create a recipe for a vegetarian pasta dish. I’m cooking for a dinner party where one guest is allergic to nuts. I have tomatoes, spinach, garlic, and various pasta shapes in my pantry. Present the recipe in a numbered list with ingredients followed by steps. The recipe should take no more than 30 minutes to prepare and cook. Here’s a sample format:&lt;br&gt;&lt;br&gt;
Ingredients:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 cup flour
&lt;/li&gt;
&lt;li&gt;2 eggs Steps:
Instructions:
&lt;/li&gt;
&lt;li&gt;Mix flour and eggs
&lt;/li&gt;
&lt;li&gt;Knead the dough&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Types of Prompts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-shot prompts:&lt;/strong&gt; A direct question or instruction without providing any examples. It is like asking your smart friend to do something they’ve never done before, but you trust they can figure it out. Example: &lt;em&gt;What is the capital of France?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-Shot Prompts:&lt;/strong&gt; These prompts provide a single example to the AI model before asking a related question. It’s like you’re giving your friend a couple of examples to follow. It’s like saying, “Here’s how it’s done, now you try!”. Example: &lt;em&gt;A cat is a pet. A dog is a pet. What is a rabbit?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chain-of-thought prompts:&lt;/strong&gt; These prompts encourage the AI to break down a complex problem into smaller, more manageable steps, guiding it toward a solution. This is when you ask your AI friend to show their work. It’s like saying, “Walk me through how you’re thinking about this.”. Example: &lt;em&gt;If I have 2 apples and buy 3 more, how many apples do I have in total? First, add the apples together, then give the total.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In essence:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Zero-shot:&lt;/strong&gt; “Here’s a task. Do it.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-shot:&lt;/strong&gt; “Here’s an example. Do a similar task.”&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chain-of-thought:&lt;/strong&gt; “Here’s a task. Break it down into smaller steps and solve it.”&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, we learned not only what prompt and prompt engineering are but also which type of prompt is suitable for different situations. You can’t utilize an LLM effectively unless you know how to pass the right instructions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/introduction-to-prompt-engineering/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on September 27, 2024.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llm</category>
      <category>promptengineering</category>
      <category>largelanguagemodels</category>
    </item>
    <item>
      <title>Introduction to LLM</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Mon, 16 Sep 2024 19:00:40 +0000</pubDate>
      <link>https://dev.to/kadnan/introduction-to-llm-21b3</link>
      <guid>https://dev.to/kadnan/introduction-to-llm-21b3</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi237g6sj443ckf4wbqhe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi237g6sj443ckf4wbqhe.png" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I am starting this &lt;a href="https://blog.adnansiddiqi.me/tag/genai" rel="noopener noreferrer"&gt;GenAI&lt;/a&gt; series where I will share insights related to GenAI and large language models (LLMs). This is the first post, where I’ll discuss what LLMs are, how they work, and other related topics.&lt;/p&gt;

&lt;h3&gt;
  
  
  What are Large Language Models
&lt;/h3&gt;

&lt;p&gt;Large Language Models, or LLMs, are a type of AI that can understand and generate human-like text. They’re the technology behind smart chatbots and writing tools, making our interactions with machines feel more natural.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwzxvgj8pzr1oqjlge2q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwzxvgj8pzr1oqjlge2q.png" width="241" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;LLMs are built on foundation models. These foundation models are large AI models pre-trained on vast amounts of unlabeled and self-supervised data to perform a wide range of tasks, serving as the base for specialized applications. This means the model learns from patterns in the data, allowing it to generate generalizable and adaptable outputs. LLMs are a specific type of foundation model, designed for text and text-related tasks. They are trained on massive amounts of text, such as books, articles, and conversations. When I say “large,” I’m referring to models trained on data measured in petabytes, and their size can range in the tens of gigabytes. LLMs are also large in terms of parameter count-parameters being values the model adjusts as it learns. The more parameters, the more complex the model. For instance, GPT-3 has 175 billion parameters, GPT-4 around 1 trillion, LLaMA has 13 billion, and Anthropic’s Claude 1 has 52 billion parameters.&lt;/p&gt;

&lt;h3&gt;
  
  
  How LLMs work
&lt;/h3&gt;

&lt;p&gt;LLMs are based on three major components: Data, Architecture, and Training. The data part is already covered above. The architecture is based on a neural network, and for GPT, that is a &lt;em&gt;transformer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Transformers are a type of AI model designed to process and understand data, especially text, in a highly efficient way. They use a mechanism called &lt;em&gt;attention&lt;/em&gt; to focus on important parts of the input, allowing them to handle long text sequences and capture complex relationships between words. During training, the model learns to predict the next word in a sentence. For instance, “Dog is a bird,” after multiple iterations and parameter adjustments, it matches the desired output: “Dog is an animal.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Fine-tuned models
&lt;/h3&gt;

&lt;p&gt;A fine-tuned model is a specific LLM that is trained on a specific kind of data to serve a niche. For instance, a medLLM is an LLM trained on all the data related to the medical field, hence giving more specific information to that field instead of giving wrong information or &lt;em&gt;hallucinating&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Hullicinatation
&lt;/h3&gt;

&lt;p&gt;In the context of LLMs, hallucination refers to instances when the model generates information that is incorrect, misleading, or completely made up, even though it sounds plausible. These hallucinations can occur because the model doesn’t actually know facts but instead predicts likely text based on patterns from its training data, sometimes producing false or non-existent information. Besides fine-tuning, you can reduce it by providing better input, aka a &lt;em&gt;prompt&lt;/em&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Large Language Model (LLM) Applications
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Customer Support&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;:&lt;/em&gt; You can create AI-based smart chat/voice bots that can replace human customer representatives and handle frequent queries. You can train an LLM using your organization’s data, FAQs, and other relevant resources to help respond effectively. For example, in the company I work for, I developed an AI-based chatbot that leverages OpenAI APIs to respond to customers. Ticket-related information is fetched via our internal API in JSON format, which is then provided to an OpenAI Assistant. The assistant responds to customers based on the ticket data in JSON format, PDFs from our knowledge base, and our custom prompt that sets a specific tone and persona.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Content Creation:&lt;/em&gt;&lt;/strong&gt; You can use LLMs to create articles, emails, video scripts, and a lot more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Translation:&lt;/em&gt;&lt;/strong&gt; You can use LLMs to translate text from one language to another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Software Development:&lt;/em&gt;&lt;/strong&gt; You can use LLMs to generate code or even fix existing code. LLMs can write tests for you and do a lot more, even converting code snippets from one language to another.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Sentiment Analysis:&lt;/em&gt;&lt;/strong&gt; LLMs are good for sentiment analysis. It doesn’t take much time to come up with something like &lt;a href="https://blog.adnansiddiqi.me/create-stock-sentiment-analysis-in-python-using-chatgpt/" rel="noopener noreferrer"&gt;this&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, we discussed what LLMs are, how they work, and how they can be beneficial in different use cases. In the coming posts, we will discuss further how you, as a programmer, can leverage your existing coding skills to make apps and earn money. Stay tuned!&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/introduction-to-llm/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on September 16, 2024.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>llmapplications</category>
      <category>llm</category>
      <category>genai</category>
      <category>largelanguagemodels</category>
    </item>
    <item>
      <title>Introduction to trading for programmers</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Fri, 13 Sep 2024 19:00:48 +0000</pubDate>
      <link>https://dev.to/kadnan/introduction-to-trading-for-programmers-5cp0</link>
      <guid>https://dev.to/kadnan/introduction-to-trading-for-programmers-5cp0</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv4l68kpal9iijebg6vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnv4l68kpal9iijebg6vh.png" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I am starting a new series, &lt;a href="https://blog.adnansiddiqi.me/tag/t4p/" rel="noopener noreferrer"&gt;&lt;em&gt;Trading for Programmers (T4P)&lt;/em&gt;&lt;/a&gt;, where I will cover topics related to trading and how programmers can leverage their existing skills. This is the first post in the series.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Programmers Should Explore Trading
&lt;/h3&gt;

&lt;p&gt;Before diving into trading, it’s important to understand why programmers should consider getting into it, even if they aren’t particularly fond of trading.&lt;/p&gt;

&lt;p&gt;Trading might seem like a world of its own, but it’s actually a great fit for those skilled in computers and numbers. At its core, trading involves buying and selling assets like stocks or cryptocurrencies to make a profit. For programmers, this can be especially intriguing because it’s akin to solving a puzzle with real-world outcomes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why is trading appealing for programmers?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Problem-Solving Skills&lt;/strong&gt; : Just like coding, trading requires identifying patterns and making decisions based on data. It’s a great way to apply your logical thinking in a different context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation:&lt;/strong&gt; Programmers love automating tasks, and trading is no exception. You can write code to automate trades, creating your own trading bots to handle the work for you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data Crunching:&lt;/strong&gt; If you enjoy working with data, trading offers a chance to analyze numbers and trends to make smart decisions. You can use your data skills to predict market movements and find good trading opportunities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Earn Money:&lt;/strong&gt; You can earn money by developing your own trading algorithms, taking on freelance projects to build trading tools, or offering consulting services to others in the trading space. If you search on websites like Upwork, you can easily get gigs that are in the range of $40-$150 per hour, sometimes even more!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hope it has sparked a bit of interest in you about trading, so now let’s talk about what is trading all about and other related things.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Trading
&lt;/h3&gt;

&lt;p&gt;Trading in simple language is all about buying securities: stocks, currencies, crypto, commodities, bonds, and derivatives. Traders can include individuals like you and me, financial institutions like banks, mortgage companies, investment banks, or institutional investors like hedge funds, insurance companies, and pension funds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stock Market History
&lt;/h3&gt;

&lt;p&gt;Although today multiple markets exist, it wasn’t always that way. Here’s a timeline of major events in the stock market’s history:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Late 1400s:&lt;/strong&gt; Antwerp, now in Belgium, becomes a major hub for international trade. Merchants begin buying goods in anticipation of price increases, with some early bond trading also taking place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1611:&lt;/strong&gt; Amsterdam sees the creation of the first modern stock exchange with the Dutch East India Company. It becomes the first publicly traded company and dominates trading activity for years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Late 1700s:&lt;/strong&gt; A group of merchants signs the Buttonwood Tree Agreement, marking the beginning of organized stock trading. This practice eventually evolved into what is now the New York Stock Exchange.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1790:&lt;/strong&gt; The Philadelphia Stock Exchange is established, contributing to the growth of the U.S. financial sector and supporting the nation’s westward expansion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1896:&lt;/strong&gt; The Dow Jones Industrial Average is introduced, initially featuring 12 companies primarily from the industrial sector.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1923:&lt;/strong&gt; The precursor to the S&amp;amp;P 500 is created by Henry Barnum Poor’s company, Poor’s Publishing. The index started tracking 90 stocks in 1926.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Types of Trading
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Day Trading&lt;/strong&gt; : Buying and selling assets within the same trading day to profit from short-term price movements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Swing Trading&lt;/strong&gt; : Holding positions for several days to capitalize on short- to medium-term trends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalping&lt;/strong&gt; : Making numerous trades in a day to capture small price changes and accumulate profits.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Position Trading&lt;/strong&gt; : Holding assets for weeks, months, or even years based on long-term trends and fundamentals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Algorithmic Trading&lt;/strong&gt; : Using computer programs and algorithms to execute trades based on predefined criteria.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High-Frequency Trading (HFT)&lt;/strong&gt;: Executing a large number of trades at extremely high speeds using advanced algorithms.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trend Following&lt;/strong&gt; : Trading based on the direction of market trends, buying in uptrends and selling in downtrends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contrarian Trading&lt;/strong&gt; : Taking positions that go against prevailing market sentiment, betting that trends will reverse.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Position in Trading
&lt;/h3&gt;

&lt;p&gt;In trading and investing, a position refers to the amount of a particular asset that an individual or entity owns or has committed to in the market. Positions can be categorized into two main types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Long Position&lt;/strong&gt; : This is when a trader or investor buys an asset with the expectation that its price will rise. They hold the asset with the intent of selling it later at a higher price for a profit.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short Position&lt;/strong&gt; : This is when a trader or investor sells an asset they do not own, intending to buy it back at a lower price. They borrow the asset to sell it and hope to repurchase it later at a lower price, profiting from the difference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Positions reflect whether someone is betting on the market to go up or down and determine the exposure to market movements.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is Assets
&lt;/h3&gt;

&lt;p&gt;In trading, an asset is anything you can buy or sell to make money. It could be something like a stock in a company, a piece of real estate, or even a cryptocurrency like Bitcoin. Essentially, it’s something valuable that you own or trade with the hope that its value will increase so you can sell it for a profit.&lt;/p&gt;

&lt;p&gt;Here are some common types of assets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Stocks&lt;/strong&gt; : Shares of ownership in a company, representing a claim on its earnings and assets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bonds&lt;/strong&gt; : Debt securities issued by governments or corporations that pay interest over time and return the principal at maturity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real Estate&lt;/strong&gt; : Physical properties like land, residential, or commercial buildings that can be bought, sold, or rented.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commodities&lt;/strong&gt; : Raw materials or primary agricultural products, such as gold, oil, or wheat, that are traded on exchanges.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cryptocurrencies&lt;/strong&gt; : Digital or virtual currencies using cryptography for security, like Bitcoin or Ethereum.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutual Funds&lt;/strong&gt; : Investment funds that pool money from many investors to buy a diversified portfolio of stocks, bonds, or other securities.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETFs (Exchange-Traded Funds)&lt;/strong&gt;: Investment funds traded on stock exchanges, similar to stocks, that hold a variety of assets like stocks or bonds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cash and Cash Equivalents&lt;/strong&gt; : Liquid assets like cash itself or short-term investments are easily converted to cash, such as Treasury bills.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derivatives&lt;/strong&gt; : Financial contracts whose value is derived from the performance of underlying assets, such as options or futures contracts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trading Analysis and its Types
&lt;/h3&gt;

&lt;p&gt;In trading, there are primarily three types of analysis that traders use to make informed decisions: &lt;strong&gt;technical analysis&lt;/strong&gt; , &lt;strong&gt;fundamental analysis&lt;/strong&gt; , and &lt;strong&gt;sentiment analysis&lt;/strong&gt;. Each of these approaches offers unique insights into market behavior and can be used individually or in combination for a well-rounded trading strategy:&lt;/p&gt;

&lt;h4&gt;
  
  
  Fundamental Analysis
&lt;/h4&gt;

&lt;p&gt;Fundamental analysis focuses on evaluating a security’s intrinsic value by analyzing financial statements, economic indicators, and other qualitative and quantitative factors.&lt;/p&gt;

&lt;p&gt;Key aspects of fundamental analysis include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Company Financials:&lt;/strong&gt; In stock trading, this involves examining earnings, revenue, and debt-to-equity ratios to assess a company’s health.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Economic Indicators:&lt;/strong&gt; For forex, analyzing interest rates, employment data, and inflation reports.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Market Sentiment:&lt;/strong&gt; Understanding how broader economic factors, like geopolitical events, affect markets.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Technical Analysis
&lt;/h4&gt;

&lt;p&gt;Technical analysis involves evaluating past market data, primarily price and volume, to forecast future price movements. Traders use various tools, such as charts, indicators (e.g., RSI, MACD), and patterns (e.g., head and shoulders, triangles), to identify trends and potential trading opportunities.&lt;/p&gt;

&lt;p&gt;Key components of technical analysis include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Price Action:&lt;/strong&gt; Analyzing historical prices to spot trends and reversals.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indicators and Oscillators:&lt;/strong&gt; Tools like moving averages, Bollinger Bands, and stochastic oscillators that help identify overbought or oversold conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chart Patterns:&lt;/strong&gt; Recognizing formations like double tops, flags, and wedges that suggest potential market moves&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Sentiment Analysis
&lt;/h4&gt;

&lt;p&gt;Sentiment analysis involves gauging the overall mood of the market or crowd to predict how future price movements might unfold. This approach looks at how optimistic or pessimistic traders feel about a particular asset or market in general. Sentiment can be measured using various tools, such as the put/call ratio, VIX (volatility index), or surveys.&lt;/p&gt;

&lt;p&gt;Key components of sentiment analysis include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;News Analysis:&lt;/strong&gt; Monitoring headlines, social media, and public sentiment to gauge market mood.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contrarian Indicators:&lt;/strong&gt; Tools like the Fear and Greed Index that highlight when the market may be overly emotional, suggesting a possible correction or reversal.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Signals
&lt;/h3&gt;

&lt;p&gt;In trading, “signals” are indicators or clues that help you decide when to buy or sell an asset. These signals can come from various sources, like charts showing price movements, news about a company, or patterns that suggest a price might go up or down. Think of signals as helpful hints or tips that guide your trading decisions, making it easier to spot good opportunities and avoid mistakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trading Strategy
&lt;/h3&gt;

&lt;p&gt;A trading strategy is a plan you follow to decide about buying and selling assets. Think of it like a set of rules or guidelines that help you decide when to enter or exit a trade. This plan is based on things like market trends, price patterns, or specific goals you have. Having a strategy helps you make more consistent and informed decisions, rather than just guessing or reacting to the market at the moment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, we discussed the basic terminologies related to trading that will be helpful in future posts. If you’re curious, you can learn more about them on YouTube or other resources. My purpose was to provide a basic introduction to these terms. Stay tuned, as we’ll now cover how you can use your programming skills in the world of trading.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/introduction-to-trading-for-programmers/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on September 13, 2024.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>tradingbot</category>
      <category>trading</category>
      <category>python</category>
    </item>
    <item>
      <title>Scraping HTML Data with BeautifulSoup [2024 Guide]</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Thu, 25 Jul 2024 13:28:29 +0000</pubDate>
      <link>https://dev.to/kadnan/scraping-html-data-with-beautifulsoup-2024-guide-39ed</link>
      <guid>https://dev.to/kadnan/scraping-html-data-with-beautifulsoup-2024-guide-39ed</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1e3sdzamsjwuorzhxxf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg1e3sdzamsjwuorzhxxf.jpg" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever wondered how to pull out useful information from websites without the hassle? BeautifulSoup is your go-to tool for scraping HTML data effortlessly.&lt;/p&gt;

&lt;p&gt;In this article, we’ll walk you through the basics of web scraping using BeautifulSoup. No prior experience is needed! With its simple syntax and straightforward approach, you’ll quickly grasp the essentials of parsing HTML and extracting data from web pages.&lt;/p&gt;

&lt;p&gt;Join us as we explore the world of web scraping in a beginner-friendly way. By the end, you’ll be equipped with the skills to gather valuable insights from any website with ease. Let’s dive in and uncover the magic of BeautifulSoup together!&lt;/p&gt;

&lt;p&gt;You can use BeautifulSoup to find and extract data by using it to go through the structure of the webpage. You can specify what part you want to find by mentioning things like tags (like &lt;/p&gt;
&lt;p&gt; for paragraphs), classes (like "header" for the header section), or XPath expressions (which are like paths to specific elements). BeautifulSoup then helps you find these parts so you can work with them, making it easier to grab data or make changes to the webpage using Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step1: Create a BeautifulSoup Object:
&lt;/h3&gt;

&lt;p&gt;Initialize a BeautifulSoup object with the HTML content:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;html_content = "&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello, World!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;"
soup = BeautifulSoup(html_content, 'html.parser')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step2: Accessing HTML Elements:
&lt;/h3&gt;

&lt;p&gt;BeautifulSoup provides various methods for accessing elements in the HTML document. Here are some common approaches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1_tag = soup.h1
print(h1_tag.text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  b. Using HTML Tags and Class:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1_with_class = soup.find('h1', class_='example-class')
print(h1_with_class.text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  c.Using XPath:
&lt;/h4&gt;

&lt;p&gt;To use XPath with BeautifulSoup, you need to install the &lt;code&gt;lxml&lt;/code&gt; parser: pip install lxml&lt;/p&gt;

&lt;p&gt;Then, you can find elements using XPath expressions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup
html_content = "&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Hello, World!&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;
soup = BeautifulSoup(html_content, 'lxml')
h1_xpath = soup.find(xpath='//h1')
print(h1_xpath.text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BeautifulSoup simplifies the process of parsing HTML documents in Python. It offers a range of methods to access and manipulate elements, making it a powerful tool for web scraping and data extraction tasks. Whether you’re a beginner or an experienced developer, BeautifulSoup provides a user-friendly interface for working with HTML content.&lt;/p&gt;

&lt;p&gt;BeautifulSoup is a helpful friend for Python programmers who want to scrape data from websites. It’s a special tool that helps us understand the structure of web pages (which are written in HTML or XML). With BeautifulSoup, we can easily find and extract specific information from those pages. It’s like having a magnifying glass for web data!&lt;/p&gt;

&lt;p&gt;BeautifulSoup is commonly used in web scraping to extract data from HTML or XML documents. It serves as a parsing library, allowing developers to navigate through the structure of web pages and locate specific elements of interest, such as text, links, or images.&lt;/p&gt;

&lt;p&gt;Here’s how BeautifulSoup is typically used in web scraping:&lt;/p&gt;

&lt;p&gt;Overall, BeautifulSoup simplifies the web scraping process by providing a user-friendly interface for parsing and extracting data from HTML or XML documents.&lt;/p&gt;

&lt;p&gt;Whether you’re extracting data from web pages for analysis or automating web scraping tasks, BeautifulSoup offers a straightforward approach to navigating and manipulating HTML content.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing BeautifulSoup
&lt;/h3&gt;

&lt;p&gt;Before you can start parsing HTML with BeautifulSoup, you’ll need to install the library. You can easily do this using pip, the Python package manager:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install beautifulsoup4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you’re ready to begin parsing HTML documents with BeautifulSoup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example HTML to Parse
&lt;/h3&gt;

&lt;p&gt;Here’s a simple example of HTML that we’ll use for parsing with BeautifulSoup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Sample HTML Page&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Welcome to BeautifulSoup!&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This is a sample HTML page for parsing with BeautifulSoup.&amp;lt;/p&amp;gt;
    &amp;lt;ul&amp;gt;
        &amp;lt;li&amp;gt;Item 1&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;Item 3&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This HTML document contains a heading , a paragraph , and an unordered list with three list items &lt;/p&gt;

&lt;ul&gt; &lt;li&gt; . It's a straightforward example showcasing different elements commonly found in HTML documents. We'll use this HTML to demonstrate how to parse it using BeautifulSoup.
&lt;h3&gt;
  
  
  Parsing Your First HTML with BeautifulSoup
&lt;/h3&gt;

&lt;p&gt;Certainly! Here’s how you can parse the provided HTML using BeautifulSoup in Python:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup

# Provided HTML content
html_content = """
&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Sample HTML Page&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Welcome to BeautifulSoup!&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This is a sample HTML page for parsing with BeautifulSoup.&amp;lt;/p&amp;gt;
    &amp;lt;ul&amp;gt;
        &amp;lt;li&amp;gt;Item 1&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;Item 2&amp;lt;/li&amp;gt;
        &amp;lt;li&amp;gt;Item 3&amp;lt;/li&amp;gt;
    &amp;lt;/ul&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
"""

# Create a BeautifulSoup object
soup = BeautifulSoup(html_content, 'html.parser')

# Extract and print the title of the HTML document
title = soup.title.text
print("Title:", title)

# Extract and print the text of the paragraph
paragraph = soup.p.text
print("Paragraph:", paragraph)

# Extract and print each item in the unordered list
print("Items in the list:")
list_items = soup.find_all('li')
for item in list_items:
    print("-", item.text)

#Output:
Title: Sample HTML Page
Paragraph: This is a sample HTML page for parsing with BeautifulSoup.
Items in the list:
- Item 1
- Item 2
- Item 3
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This code demonstrates how to create a BeautifulSoup object, extract the title, and paragraph text, and list items from the provided HTML content. BeautifulSoup makes it easy to navigate through the HTML structure and access specific elements, making it an excellent tool for web scraping and data extraction tasks.&lt;/p&gt;

&lt;p&gt;Parsing a local HTML file with BeautifulSoup involves several straightforward steps. Below is a step-by-step guide on how to achieve this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; : Import BeautifulSoup and Open the HTML File&lt;/p&gt;

&lt;p&gt;First, you need to import the BeautifulSoup library and open the HTML file using Python’s built-in file handling capabilities.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from bs4 import BeautifulSoup # Open the HTML file with open("example.html", "r") as file: html_content = file.read() soup = BeautifulSoup(html_content, 'html.parser')
&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Step 3: Find Elements in the HTML
&lt;/h3&gt;

&lt;p&gt;Now, you can use BeautifulSoup’s methods to find elements within the HTML file. For example, to find all the paragraph tags &lt;/p&gt;

&lt;p&gt; , you can use:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Find all paragraph tags
paragraphs = soup.find_all('p')
&lt;/code&gt;&lt;/pre&gt;



&lt;h3&gt;
  
  
  Step 4: Extract Data or Perform Actions
&lt;/h3&gt;

&lt;p&gt;With the elements found, you can extract data or perform actions as needed. For instance, you can loop through the paragraphs and print their text content:&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Find all paragraph tags
paragraphs = soup.find_all('p')
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;Once you’re done parsing the HTML file, it’s good practice to close the file.&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Find all paragraph tags
paragraphs = soup.find_all('p')
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;There are three common ways to query the DOM tree using BeautifulSoup in Python, each offering different levels of specificity and flexibility for extracting data from HTML documents.&lt;/p&gt;

&lt;p&gt;, and you want to find the first &lt;strong&gt;Using Python Object Attributes&lt;/strong&gt; : One way to query the DOM tree is by directly accessing elements through Python object attributes. For example, if you have a BeautifulSoup object called &lt;code&gt;soup&lt;/code&gt; tag, you can simply access it like an attribute: &lt;/p&gt;

&lt;h1&gt;
&lt;br&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soup.h1
&lt;/code&gt;&lt;/pre&gt;
&lt;/h1&gt;



&lt;p&gt;Another approach is to use the method provided by BeautifulSoup. This method allows you to specify the tag name and optionally other attributes to find the first matching element. For instance, to find the first &lt;strong&gt;Using BeautifulSoup .find() Method&lt;/strong&gt;.find() &lt;/p&gt;

&lt;p&gt; tag with a class of "intro"&lt;br&gt;
&lt;/p&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soup.find('p', class_='intro')
&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The method is similar to &lt;strong&gt;Using BeautifulSoup .find_all() Method&lt;/strong&gt;find_all() .find() , but it returns a list of all matching elements instead of just the first one. This is useful when you want to find multiple elements that match certain criteria. For example, to find all &lt;a&gt; tags within a  with the class "menu" :&lt;br&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;soup.find_all('a', attrs={'class': 'menu'})
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;Scraping a few pages is manageable, but what happens when you need to scrape hundreds of thousands? Your IP could get blocked or throttled, bringing your project to a halt. The solution? Use multiple proxies with the right settings to avoid these roadblocks. Enter ScraperAPI-a powerful, cloud-based platform that makes web scraping and data extraction effortless. Just hit the endpoint, and ScraperAPI handles the rest, managing proxies and preventing issues. Ready to supercharge your scraping?&lt;/em&gt; &lt;a href="http://scraperapi.com/?via=adnan98" rel="noopener noreferrer"&gt;&lt;em&gt;Sign up&lt;/em&gt;&lt;/a&gt; &lt;em&gt;for ScraperAPI now, and use my promo code&lt;/em&gt; &lt;strong&gt;&lt;em&gt;adnan10&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;to enjoy a&lt;/em&gt; &lt;strong&gt;&lt;em&gt;10% discount&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;. If you encounter any issues with the discount, reach out to me via email on my site, and I’ll be happy to assist you.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Mastering web scraping with BeautifulSoup is like having a handy tool that effortlessly extracts valuable data from websites. This article breaks down the process into easy steps, making it accessible even to beginners. BeautifulSoup acts as your helpful guide, simplifying the technicalities of HTML parsing and navigation. With its user-friendly approach, you’ll find yourself confidently exploring web pages and extracting the information you need. Remember, curiosity and perseverance are your allies as you embark on this journey. With BeautifulSoup as your companion, you’ll uncover hidden insights across the vast expanse of the internet. So keep learning, keep exploring, and let BeautifulSoup empower you in the world of data extraction and analysis.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/scraping-html-data-with-beautifulsoup-2024-guide/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on July 25, 2024.&lt;/em&gt;&lt;/p&gt;

&lt;/a&gt;&lt;/p&gt;

&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>webscraping</category>
      <category>beautifulsoup</category>
      <category>python</category>
    </item>
    <item>
      <title>Getting started with OpenAI Assistant APIs and Python</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Sun, 12 May 2024 22:16:03 +0000</pubDate>
      <link>https://dev.to/kadnan/getting-started-with-openai-assistant-apis-and-python-4hdp</link>
      <guid>https://dev.to/kadnan/getting-started-with-openai-assistant-apis-and-python-4hdp</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpot1ob4mffu9r71zg6ox.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpot1ob4mffu9r71zg6ox.jpeg" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Earlier I had discussed using &lt;a href="https://blog.adnansiddiqi.me/building-an-e-commerce-product-recommendation-system-with-openai-embeddings-in-python/" rel="noopener noreferrer"&gt;OpenAI Embeddings&lt;/a&gt; API to come up with a product recommendation system. In this post, I am going to discuss Assistant APIs, The APIs OpenAI provided to integrate custom GPTs. I am going to create a blog title generator in Flask that will be generating blog titles in the tech/gadget space. In case you are in a hurry you may want to watch the demo video of it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/media/2e87b77cda85992d38dd1c7809ea0ffc/href" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://medium.com/media/2e87b77cda85992d38dd1c7809ea0ffc/href" rel="noopener noreferrer"&gt;https://medium.com/media/2e87b77cda85992d38dd1c7809ea0ffc/href&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is a custom GPT?
&lt;/h3&gt;

&lt;p&gt;According to OpenAI:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;…ChatGPT that combine instructions, extra knowledge, and any combination of skills.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Custom GPTs, as the name says, are the customized versions of chatGPT that rely on your own data and instructions. You can instruct your version of GPT to respond in a certain format or to fetch data information from your own provided knowledge.&lt;/p&gt;

&lt;p&gt;One wonders, why there’s a need to integrate a custom GPT with an app. Imagine a situation where you, as a business owner, have come up with an onboarding custom GPT and you want it to be available for your staff so that they do not bother you again and again or a digital version of a professional like you or an influencer who can provide benefit to his/her followers without a need of accessing him directly. Imagine you are questioning Warren Buffet, Seth Godin, or Malcolm Gladwell. What is required to upload all content related to them and an instruction set, that’s it!&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom GPT Creation and Configuration
&lt;/h3&gt;

&lt;p&gt;As of now both custom GPTs and Assistant APIs are only available to paid users. There’s a free $5 credit that is provided to new accounts that last for 2 months. Once it’s expired you gotta pay to OpenAI guys to use their APIs.&lt;/p&gt;

&lt;p&gt;I have created a &lt;a href="https://chatgpt.com/g/g-YWqnlvEfI-tech-blog-title-generator" rel="noopener noreferrer"&gt;customGPT&lt;/a&gt; for this blog post, called &lt;strong&gt;Tech Blog Title Generator.&lt;/strong&gt; If you are a paid user and visit the link, you’ll see something like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nkwe4jb22gj1z8nmf8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nkwe4jb22gj1z8nmf8o.png" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So for instance, if I look for articles related to Google Bard, I will do something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc92w7esdpwopit4s5uk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc92w7esdpwopit4s5uk.png" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I used the following text as &lt;em&gt;Instructions&lt;/em&gt;, also I updated &lt;a href="https://www.wix.com/blog/how-to-write-catchy-blog-titles" rel="noopener noreferrer"&gt;this&lt;/a&gt; and &lt;a href="https://www.wordstream.com/blog/ws/2014/07/17/headline-writing" rel="noopener noreferrer"&gt;this&lt;/a&gt; in PDF format in the knowledge base:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Focus: Generate blog titles that are specifically related to technology and gadgets. The titles should cover the latest innovations, reviews, and insights in the tech world.Keywords Usage: Incorporate relevant keywords such as “smartphones”, “AI”, “virtual reality”, “IoT”, and “wearables”. Ensure these keywords are used logically and contextually to attract tech enthusiasts.Engagement and Curiosity: Create titles that are catchy and engaging. Use action verbs, questions, or surprising facts to spark curiosity and encourage clicks.SEO Considerations: While crafting titles, keep SEO in mind. Include primary keywords at the beginning of the title if possible. Make sure the titles are also concise, preferably under 60 characters, to perform well in search results.Format Variety: Use a variety of title formats such as questions, lists (e.g., “Top 10…”, “5 Best…”), how-tos, and guides. This helps address different reader preferences and search intents.Clarity and Accuracy: Ensure that each title accurately reflects the content of the potential blog post. Avoid misleading phrases that don’t directly relate to the content.Timeliness and Trending Topics: Focus on current and emerging trends in the technology sector. Titles should feel up-to-date and relevant to current tech discussions and advancements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You must refer the uploaded documents where needed for the better understanding.
&lt;/li&gt;
&lt;li&gt;User will input some keyword, for instance AI, or LLM and you must generate maximum two titles
&lt;/li&gt;
&lt;li&gt;You do not need to provide any explanations, You must return blog titles only&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now let’s automate this customGPT and integrate it with a web app by using OpenAI Assistant APIs. We will be &lt;a href="https://platform.openai.com/assistants" rel="noopener noreferrer"&gt;creating an assistant&lt;/a&gt; and then by using the &lt;em&gt;assistant ID&lt;/em&gt; we will be using it to ask about blog titles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0iim6e0fml8b925djinl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0iim6e0fml8b925djinl.png" width="800" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s run it by testing it on the playground&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7l9g060errq3k76lbik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr7l9g060errq3k76lbik.png" width="800" height="899"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not bad! Now the goal is to come up with a webpage where you can query like we did on the chatGPT interface and playground and get the response from the assistant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifarkulenf1jp054ctma.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fifarkulenf1jp054ctma.png" width="446" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user sends a query via our web app that is then sent to OpenAI Assistant via API which then sends a response based on your instructions and uploaded documents. I will be creating a webpage in Python Flask that will interact with our assistant via a REST API. The flow of sending/receiving messages using Assistant APis is given below ( &lt;em&gt;Credit: OpenAI&lt;/em&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3trcigageci1gz99jna.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu3trcigageci1gz99jna.png" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before I move further, I’d like to share updated instructions that are specific to the assistant only:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Focus: Generate blog titles that are specifically related to technology and gadgets. The titles should cover the latest innovations, reviews, and insights in the tech world.Keywords Usage: Incorporate relevant keywords such as “smartphones”, “AI”, “virtual reality”, “IoT”, and “wearables”. Ensure these keywords are used logically and contextually to attract tech enthusiasts.Engagement and Curiosity: Create titles that are catchy and engaging. Use action verbs, questions, or surprising facts to spark curiosity and encourage clicks.SEO Considerations: While crafting titles, keep SEO in mind. Include primary keywords at the beginning of the title if possible. Make sure the titles are also concise, preferably under 60 characters, to perform well in search results.Format Variety: Use a variety of title formats such as questions, lists (e.g., “Top 10…”, “5 Best…”), how-tos, and guides. This helps address different reader preferences and search intents.Clarity and Accuracy: Ensure that each title accurately reflects the content of the potential blog post. Avoid misleading phrases that don’t directly relate to the content.Timeliness and Trending Topics: Focus on current and emerging trends in the technology sector. Titles should feel up-to-date and relevant to current tech discussions and advancements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You must refer the uploaded documents where needed for the better understanding.
&lt;/li&gt;
&lt;li&gt;User will input some keyword, for instance AI, or LLM and you must generate maximum two titles
&lt;/li&gt;
&lt;li&gt;You do not need to provide any explanations, You must return blog titles only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;- You must return in a JSON Object array&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, I am forcing the assistant to return the response in JSON format which makes sense because, unlike the custom GPT, the assistant will be communicating with an app hence it is easier to get a response in a standardized format instead of some random one. Now when I ask a question it’d return a JSON object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm46k2gjhhgmq7vsckxud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm46k2gjhhgmq7vsckxud.png" width="800" height="757"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Integration of Web App with Assistant API
&lt;/h3&gt;

&lt;p&gt;I will not be sharing and everything here as the entire code will be available on GitHub. I am going to show how you integrate Assistant APIs with a Flask app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.route("/ask", methods=['POST'])
def ask_assistant():
    config = dotenv_values(".env")
    API_KEY = config['API_KEY']
    ASSISTANT_ID = config['ASSISTANT_ID']
    client = OpenAI(api_key=API_KEY)
    # Create Thread
    thread_id = create_thread(client)
    data = request.get_json()
    query = data['query']
    # Create Message
    message_id = create_message(client, thread_id, query)

    # Create Runa and Get Response
    message = create_run_messages(client, thread_id, ASSISTANT_ID)
    message = json.loads(message)
    return jsonify({'data': message}), 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the ask REST API takes input, communicates with Assistant API, and returns the JSON response to the web app. If everything works fine you'll see an output like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91tf7yx4be1ssvm7ealb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91tf7yx4be1ssvm7ealb.png" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The main thing is done, now you have the option to monetize your &lt;em&gt;custom GPT&lt;/em&gt;. You may give one or two free usages and then can ask to pay via Stripe or any other gateway to charge from your customers. In this way, you can not only monetize your GPTs but can also provide them to people who are not even chatGPT users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;As you see, it is so easy to convert a custom GPT into an app and make it available for those who are on a free plan of chatGPTs or not even chatGPT users at all. I have converted a few custom GPTs of my clients into web apps and made them available for their internal staff. Like always the code is available on &lt;a href="https://github.com/kadnan/Tech-Blog-Title-Generator/tree/main" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/getting-started-with-openai-assistant-apis-and-python/" rel="noopener noreferrer"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on May 12, 2024.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>llm</category>
      <category>python</category>
      <category>openai</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>Building an E-commerce Product Recommendation System with OpenAI Embeddings in Python</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Sun, 25 Feb 2024 18:52:03 +0000</pubDate>
      <link>https://dev.to/kadnan/building-an-e-commerce-product-recommendation-system-with-openai-embeddings-in-python-2pdd</link>
      <guid>https://dev.to/kadnan/building-an-e-commerce-product-recommendation-system-with-openai-embeddings-in-python-2pdd</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nvw9dhCA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aa-O4ak5mK6csZvOMo24yRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nvw9dhCA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aa-O4ak5mK6csZvOMo24yRw.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Image generated via DALL-E&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Earlier I had written a post about using &lt;a href="https://blog.adnansiddiqi.me/create-stock-sentiment-analysis-in-python-using-chatgpt/"&gt;OpenAI APIs to create a stock sentiment analysis&lt;/a&gt; by feeding news to GPT models. In this post, I am going to introduce the concepts of &lt;em&gt;Word Embeddings&lt;/em&gt; or &lt;em&gt;Embeddings&lt;/em&gt; in general. I am going to write a product recommendation system using OpenAI embeddings API that consumes product-related datasets from Kaggle. If you are in a hurry or not interested in technical details, check the demo video below:&lt;/p&gt;

&lt;a href="https://medium.com/media/4edbf273a1f70d77a7b77dd0bbd483b4/href"&gt;https://medium.com/media/4edbf273a1f70d77a7b77dd0bbd483b4/href&lt;/a&gt;

&lt;p&gt;Before I start developing the system itself, allow me to discuss a few words about embeddings and their need.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MnwqjHQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/632/0%2AfoVQvScJQLsq3yd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MnwqjHQi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/632/0%2AfoVQvScJQLsq3yd9.png" alt="" width="632" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In essence, it is a method for representing complicated data in a lower-dimensional space, such as words, sentences, photos, and videos. Consider embeddings as a means to convert words or sentences into numeric representations. Every word or phrase has a distinct set of numbers assigned to it, and these numbers convey the context and meaning of the words. Computers can so comprehend and manipulate the underlying meaning of the words rather than merely text by using these numbers. It is similar to assigning a unique code to every word to improve the computer’s linguistic comprehension.&lt;/p&gt;

&lt;p&gt;Imagine you have a box filled with tons of toys, all jumbled together. It’s fun to play with them, but sometimes it’s hard to find the one you want because everything is mixed up.&lt;/p&gt;

&lt;p&gt;Embeddings are like a special sorting game for your toys! They take each toy and give it a secret sticker with just a few colored dots on it. Each dot stands for something special about the toy, like its color, size, or what it makes a sound.&lt;/p&gt;

&lt;p&gt;Now, instead of looking at all the toys at once, you can just look at their stickers. If two stickers have the same colors in the same places, that means the toys are probably similar! This makes it much easier to find the toy you want, even if it’s hiding in a big pile.&lt;/p&gt;

&lt;p&gt;That’s what embeddings do with grown-up things like words, pictures, and even music! They turn them into small codes that capture what’s important about them, so computers can understand them better and do cool things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Show you pictures of dogs when you search for “furry friend”&lt;/li&gt;
&lt;li&gt;Recommend books you might like based on other stories you enjoyed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, while embeddings might sound complicated, they’re really just a clever way to organize and understand things by using secret codes!&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Are Embeddings Called ‘Embeddings’?
&lt;/h3&gt;

&lt;p&gt;The term “embedding” is derived from the concept of embedding something into a space with fewer dimensions. In the context of word embeddings, words are represented as vectors (mathematical entities with both magnitude and direction) in a continuous vector space. This process allows words to be positioned in a way that captures their semantic relationships and contextual meanings. Here are some potential interpretations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Embedding like embedding a gem:&lt;/strong&gt; Imagine a precious gem set within a ring. The gem (complex data) is embedded within the ring (simpler space), preserving its essence while being integrated into a new structure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding is like embedding oneself in a culture:&lt;/strong&gt; Immersing yourself in a different culture involves understanding its nuances and relationships within its structure. Similarly, embeddings capture the “meaning” of data by understanding its connections within a lower-dimensional space.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedding like encoding information:&lt;/strong&gt; Embedding involves encoding complex data using a more concise representation, akin to how information is “embedded” within symbols or codes. It’s not a direct translation, but rather a compressed version retaining key aspects.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  How are word embeddings made?
&lt;/h3&gt;

&lt;p&gt;Large text datasets train neural network models, which create word embeddings. Word2Vec and GloVe are two popular techniques for generating word embeddings, while there are other methods as well. Several algorithms contribute to the exciting world of word embeddings, each with its strengths and weaknesses. Here are some of the most prominent:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Word2Vec:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This popular option features two variants: &lt;strong&gt;Continuous Bag-of-Words (CBOW)&lt;/strong&gt; and &lt;strong&gt;Skip-gram&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CBOW&lt;/strong&gt; predicts a target word based on its surrounding context words, helping capture semantic relationships.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skip-gram&lt;/strong&gt; predicts surrounding context words based on a single input word, focusing on capturing syntactic nuances.&lt;/li&gt;
&lt;li&gt;Both rely on neural networks and offer efficient representation of frequent words.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. GloVe (Global Vectors for Word Representation):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This algorithm leverages statistical information from co-occurrence matrices, analyzing how often words appear together in a corpus.&lt;/li&gt;
&lt;li&gt;It aims to capture both semantic and syntactic information, offering good performance for rare words.&lt;/li&gt;
&lt;li&gt;While not utilizing neural networks, it allows for faster training and larger vocabulary handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. FastText:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This extension of Word2Vec incorporates subword information, breaking words into smaller meaningful units (e.g., morphemes).&lt;/li&gt;
&lt;li&gt;This allows for handling out-of-vocabulary words by combining subword embeddings, making it adaptable to diverse vocabularies.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. ELMo (Embeddings from Language Models):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This contextual word embedding approach analyzes words based on their entire sentence context, utilizing a bidirectional language model.&lt;/li&gt;
&lt;li&gt;This captures dynamic word meanings depending on the sentence, suitable for tasks like sentiment analysis and text summarization.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. BERT (Bidirectional Encoder Representations from Transformers):&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Use Cases of Embeddings:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;Text&lt;/em&gt;:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation systems:&lt;/strong&gt; Suggest similar products, articles, or music based on user preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chatbots and virtual assistants:&lt;/strong&gt; Understand user queries and respond in a relevant and human-like way.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sentiment analysis:&lt;/strong&gt; Classify the sentiment of text (positive, negative, neutral) for targeted marketing or social media analysis.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine translation:&lt;/strong&gt; Translate text from one language to another while preserving meaning and context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text summarization:&lt;/strong&gt; Generate concise summaries of large bodies of text.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Images&lt;/em&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image search and retrieval:&lt;/strong&gt; Find similar images based on their content and visual features.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image classification:&lt;/strong&gt; Categorize images into different classes (e.g., animals, objects, landscapes).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Image captioning:&lt;/strong&gt; Automatically generate captions for images that describe their content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anomaly detection:&lt;/strong&gt; Identify unusual or suspicious images in large datasets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Other Data Types:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation systems for products, movies, etc.:&lt;/strong&gt; Similar to text recommendations, using product features or user preferences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fraud detection:&lt;/strong&gt; Identify fraudulent transactions or activities based on user behavior patterns.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Drug discovery:&lt;/strong&gt; Find new drugs by analyzing molecular structures and their similarities to known drugs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social network analysis:&lt;/strong&gt; Understand relationships and communities within networks of users.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Additionally:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Embeddings can be used for dimensionality reduction, making complex data easier to process and analyze.&lt;/li&gt;
&lt;li&gt;They can be combined with other machine learning techniques to improve the performance of various tasks.&lt;/li&gt;
&lt;li&gt;As research advances, new and innovative applications for embeddings are constantly emerging.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alright..enough theoretical information has been provided, let’s start writing some code, shall we?&lt;/p&gt;
&lt;h3&gt;
  
  
  Development
&lt;/h3&gt;

&lt;p&gt;As mentioned, I will develop a product recommendation system using Walmart data from &lt;a href="https://www.kaggle.com/datasets/promptcloud/walmart-product-data-2019"&gt;Kaggle.&lt;/a&gt; Though it contains items from multiple categories I specifically extracted food-related items for further development. Before I start coding, let me share the entire flow of the system.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7TowdhSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/121/0%2A4xQIIoVwqSjjHV1j.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7TowdhSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/121/0%2A4xQIIoVwqSjjHV1j.jpeg" alt="" width="121" height="761"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Look simple, right? It is! I have divided the code into two parts: a Jupyter notebook for explaining the purpose and a Python Flask application to display similar products. I will be sharing code later in a repo so hence discussing the main parts of the program. So let’s discuss one by one. We will be loading API_KEY which is defined in .env file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from dotenv import dotenv_values
config = dotenv_values(".env") 
OPENAI_EMBEDDINGS_KEY = config['API_KEY']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loading Products CSV and Filtering
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;csv_file = 'walmart.csv'
text_columns = ['Product Url', 'Product Name', 'Description','List Price', 'Brand']

df = pd.read_csv(csv_file)
missing_values = df['Category'].isna().any()
if missing_values:
    df['Category'].fillna('', inplace=True)

# Filter the DataFrame to include only records where 'Category' contains 'Foods'
df = df[df['Category'].str.contains('Foods', case=False)]

columns_to_remove = ['Crawl Timestamp', 'Item Number','Gtin','Package Size','Category','Postal Code','Available','Sale Price','Brand']
# Drop the specified columns
df.drop(columns=columns_to_remove, inplace=True)
df['Combined_CSV'] = df.apply(combine_to_csv, axis=1)
small_df = df.tail(500)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy. After loading the CSV file in a dataframe variable, df, I then filtered records from foods related categories and after removing unwanted columns I stored them in small_df variable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Combining Columns For Embedding
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Function to combine specified columns into a CSV-formatted string
def combine_to_csv(row):
    return ','.join(['"{}"'.format(str(value).strip()) if col != 'List Price' else str(value).strip() for col, value in row[['Uniq Id','Product Name', 'Description', 'List Price']].items()])

df['Combined_CSV'] = df.apply(combine_to_csv, axis=1)
small_df = df.tail(500)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function combine_to_csv just concatenate the relevant columns' data in CSV format and store them in a new column Combined_CSV. Later, this column will be used to create product embeddings. The small_df contains the last 500 records&lt;/p&gt;

&lt;h3&gt;
  
  
  Generate Batches and Embeddings
&lt;/h3&gt;

&lt;p&gt;Alright, the data is ready, it’s time to create embeddings. OpenAI’s create embeddings API accept either a string or an array as input. Creating multiple embeddings in a go is efficient since it makes fewer requests yet gives individual embeddings. But there’s a caveat, there is a limit to the maximum input which is 8191 for all embedding models.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tf8Ax0Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Awbnpsb11lz_UmAdT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tf8Ax0Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Awbnpsb11lz_UmAdT.png" alt="" width="800" height="203"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are going to use text-embedding-3-small model which is quite cheap and serves the purpose. So, the way to deal with it is to divide records into several batches based on the &lt;strong&gt;MAX INPUT&lt;/strong&gt;  limit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def create_batch_records(df,max_tokens=8191):
    """
    This function will iterate the df's COMBINED cloumn.
    each record will be passed to "num_tokens_from_string" function
    to calculate total tokens by each record
    """
    batch = []
    batches = []
    remaining_token = max_tokens
    for index, row in df.iterrows():
        text = row['Combined_CSV'].lower().strip()
        token_count = num_tokens_from_string(text)
        batch.append(text)
        remaining_token = remaining_token - token_count
        if token_count &amp;gt;=remaining_token:
            batches.append(batch)            
            batch = []
            remaining_token = max_tokens
    return batches,len(batches)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once batches are prepared, it’s time to create embeddings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;embedding_found = True
formatted_embeddings = []
all_embeddings = []
merged_embeddings = []
x = 0

# load the cache if it exists, and save a copy to disk
try:
    merged_embeddings = pd.read_csv("allembeds.csv")
    print("Embedding File Found")
except FileNotFoundError:
    print("Embedding File Not Found...")
    embedding_found = False

if not embedding_found:
    print("Creating Batches and Embeddings")
    batches,count = create_batch_records(small_df)
    for batch in batches:
        records,embeddings = generate_embeddings(batch,client,EMBEDDING_MODEL)
        formatted_embeddings = format_embeddings(records,embeddings)
        all_embeddings.append(formatted_embeddings)
        x+=1
        if x &amp;gt; 2: # No specific reason, did not want to consume my OpenAI account
            break 

for emb in all_embeddings:
for rec in emb:
merged_embeddings.append(rec)

if not embedding_found:
  df = pd.DataFrame(merged_embeddings, columns =['UniqueID','Title','Desc','Price','Embedding'])
  df['Price'] = pd.to_numeric(df['Price'], errors='coerce').fillna(0.0)
  df.to_csv('allembeds.csv', index=False)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I am making sure that allembeds.csv exist, if it's there, then use the already computed embeddings otherwise make a call to OpenAI servers. Once embeddings are ready, I iterate all products in batches and store their embeddings into a single-dimensional array. After that stored them in allembeds.csv file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Embedding For The Input Query
&lt;/h3&gt;

&lt;p&gt;Alright! The embeddings of each product are ready and stored in the CSV file. Now I will be creating the embedding of the input query&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query = input("Enter product title")
emb_query = generate_single_embedding(query,client,EMBEDDING_MODEL)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cosine Similarity Computation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Cosine_similarity"&gt;&lt;em&gt;Cosine Similarity&lt;/em&gt;&lt;/a&gt; is one of the distant formulas used to find the nearest point against a given point. The other formulas are &lt;em&gt;Euclidean Distance&lt;/em&gt; and &lt;em&gt;Manhattan Distance.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;text_embedding_array = np.array(emb_query)
text_embedding_reshaped = text_embedding_array.reshape(1, -1)
similarities = compute_similarity(text_embedding_reshaped, extracted_embeddings)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I calculate similarities after converting into a &lt;strong&gt;&lt;em&gt;numpy&lt;/em&gt;&lt;/strong&gt; array and then from 1D to a 2D array. Below are two graphs about Cosinme Similarity and Input Query Embedding vs All Embeddings:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qAyab_06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/576/0%2AEcN4t_xWXUXglZaD.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qAyab_06--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/576/0%2AEcN4t_xWXUXglZaD.png" alt="" width="576" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--89wi2U4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/689/0%2AuZEs5dJHwcacWiJO.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--89wi2U4J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/689/0%2AuZEs5dJHwcacWiJO.png" alt="" width="689" height="547"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above charts depict the outcome of the input query, &lt;strong&gt;Health Warrior Chia Bar, Acai Berry, 25 G, Pac.&lt;/strong&gt; The red dot near a blue dot tells that the input text is very similar to this nearby blue one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Displaying Top 5 Products
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;top5 = top_5_similar_records(similarities,small_df,query)
top5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I run the above query, it produces the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[('Health Warrior Chia Bar, Acai Berry, 25 G, Pack Of 15',
  '21fee4394b9cc53bb6ddbe4235506a5c',
  0.7865167078326643),
 ('Rise Bar Gluten Free Protein Bars, Chocolatey Coconut, 2.1 Oz, 12 Ct',
  '076ce5498d181a517bdc2863142402c0',
  0.46839342705774173),
 ('Nutrisystem Chocolate Chip Baked Bars Pack, 5 Count - Ready to Eat Meal Replacement Breakfast Bars to Support Healthy Weight Loss',
  '202ab4c56b418153657e2b53b30ef9b3',
  0.4606601758761113),
 ('Pure Organic Pineapple Passion Fruit Bars 0.63 oz 12 ct',
  '269fc6604182f3c027e25280fdffb95b',
  0.4472399354429031),
 ('Go Raw 100% Organic Spirulina Super Chips, 3 oz, (Pack of 12)',
  '08b116626df671a2ad3fb1b1de9d179c',
  0.4471157111214574),
 ('Natures Way Barley Grass Bulk Powder Dietary Supplement, 9 oz',
  '18fc594859d86f440890e87bafa95ef5',
  0.43024825369566544)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first product is around 79% similar to the input query, as you can see yourself the most relevant output is &lt;strong&gt;&lt;em&gt;Health Warrior Chia Bar, Acai Berry, 25 G, Pack Of 15&lt;/em&gt;&lt;/strong&gt; while the input query contains &lt;strong&gt;&lt;em&gt;Health Warrior Chia Bar, Acai Berry, 25 G, Pac.&lt;/em&gt;&lt;/strong&gt; You might argue that the difference is subtle then why cosine similarity is &lt;strong&gt;&lt;em&gt;0.78&lt;/em&gt;&lt;/strong&gt; ( &lt;em&gt;Btw, cosine similarity ranges between 0 and 1&lt;/em&gt;), why not near 1 or even 0.9? The reason is these embeddings do not consist of the product title only but also contain the Price, UniqueID, and Description columns which would have varied from the input query to the matched product.&lt;/p&gt;

&lt;p&gt;Now it’s time to make the entire thing into a working demo. A simple Flask-based app that shows product listing from the database and then individual products with the listing of similar products.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Nn5hQ3lA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMVYFTmZT0BazOAvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Nn5hQ3lA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMVYFTmZT0BazOAvc.png" alt="" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do remember that these similar products are not based on a “Full Text” search or anything but Semantic Search.&lt;/p&gt;

&lt;p&gt;So in this post, we learned embeddings could be used for recommending relevant products. There have been many posts, in fact, products that let you question PDF files but not much about using embeddings for recommendation purposes. I hope you’d have enjoyed it. Like always, the code is available on &lt;a href="https://github.com/kadnan/ProductRecommendationUsingEmbeddings"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Interested in building something similar or other AI/LLM-related apps, contact at&lt;/em&gt; &lt;strong&gt;&lt;em&gt;kadnan @ gmail.com&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/building-an-e-commerce-product-recommendation-system-with-openai-embeddings-in-python/"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on February 25, 2024.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>openai</category>
      <category>llm</category>
      <category>textembedding</category>
      <category>recommendationsystem</category>
    </item>
    <item>
      <title>Create Your First Real Estate Lead-Capturing Chatbot Using Voiceflow and Python Flask</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Sun, 07 Jan 2024 20:58:34 +0000</pubDate>
      <link>https://dev.to/kadnan/create-your-first-real-estate-lead-capturing-chatbot-using-voiceflow-and-python-flask-gln</link>
      <guid>https://dev.to/kadnan/create-your-first-real-estate-lead-capturing-chatbot-using-voiceflow-and-python-flask-gln</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Lg3jLqZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AELoH54OOssAJrjiJ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Lg3jLqZg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AELoH54OOssAJrjiJ.png" alt="" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;Chatbots are essential tools because they make communication between people and technology much easier. These clever programs can answer questions, provide helpful information, and even assist with tasks. In various fields like real estate, chatbots play a crucial role by engaging with potential clients, enhancing user experience, and helping businesses capture valuable leads. They’re like smart assistants who work around the clock, making interactions smoother and more efficient for everyone involved.&lt;/p&gt;

&lt;p&gt;Chatbots come in different levels of complexity, categorized as either stateless or stateful. Stateless chatbots treat each conversation as if it’s a new interaction with a user, while stateful chatbots can remember and consider past exchanges when generating responses.&lt;/p&gt;

&lt;p&gt;Integrating a chatbot into a service or sales department is often a low or no-code endeavor. Numerous chatbot service providers offer tools that empower developers to create conversational user interfaces seamlessly integrated into third-party business applications.&lt;/p&gt;

&lt;p&gt;In this post, I am going to develop a real estate chatbot that will display properties from the website and then capture all information about the potential lead. I am using the &lt;a href="https://www.onthemarket.com/"&gt;OnTheMarket&lt;/a&gt; website for the sake of the demo. I am using the &lt;a href="https://voiceflow.com/"&gt;VoiceFlow chatbot platform&lt;/a&gt; which is very yet very powerful. Unlike many others, VoiceFlow provides a trial account for 2 weeks, enough to test your idea. I will be using unofficial APIs of OnTheMarket in Python Flask. There will also be a web interface to display captured leads. If you are in a hurry and want to see how it works, watch the video below:&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction to VoiceFlow
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.voiceflow.com/"&gt;VoiceFlow&lt;/a&gt; is a chatbot platform that facilitates you to create and deploy your chatbot whether they are AI-based or non-AI. It provides an easy-to-use designer to create the flow of your bot and a Javascript code snippet to deploy your bot on a website. The bot could be integrated with other platforms as well for instance WhatsApp, Instagram, etc with the help of 3rd party tools. It provides a 2-week trial which is enough to test things, plus they also offer a Sandbox mode. Visit their &lt;a href="https://www.voiceflow.com/pricing"&gt;pricing&lt;/a&gt; page for further details.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bot Development
&lt;/h3&gt;

&lt;p&gt;OK! So we are going to make a chatbot for &lt;a href="https://www.onthemarket.com/"&gt;OnTheMarket(OTM)&lt;/a&gt;, one of the famous property portals for the UK. The flow of the bot is simple; it will ask whether you want to buy a house or for rent, minimum/maximum prices, location, and the number of bedrooms, and return a list of properties within the chatbot. The user will select the properties he is interested in and then his contact details along with the preferences will be stored in the database. That’s it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rest API for properties
&lt;/h3&gt;

&lt;p&gt;First and foremost, we need some way to send user preferences to the OTM website and retrieve the relevant listings. I am creating a simple endpoint in Flask that will access the &lt;em&gt;unofficial&lt;/em&gt; OnTheMarket API to retrieve data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def search_properties(search_type, location_id, min_price, max_price, min_bedrooms, property_type):
    property_types = [
        'semi-detached',
        'terraced',
        'bungalows',
        'flats-apartments',
    ]
    search_types = [
        'to-rent',
        'for-sale',
    ]

    headers = {
        'authority': 'www.onthemarket.com',
        'accept': 'application/json',
        'accept-language': 'en-US,en;q=0.9,ur;q=0.8,zh-CN;q=0.7,zh;q=0.6',
        'cache-control': 'no-cache',
        'content-type': 'application/json; charset=utf-8',
        'dnt': '1',
        'pragma': 'no-cache',
        'referer': 'https://www.onthemarket.com/to-rent/property/london/?max-price=1250&amp;amp;min-bedrooms=1&amp;amp;min-price=100',
        'sec-ch-ua': '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"macOS"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-origin',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
    }
    params = {
        'search-type': search_type,
        'location-id': location_id,
        'min-price': min_price,
        'max-price': max_price,
        'min-bedrooms': min_bedrooms,
        'prop-types': property_types,
    }
    r = requests.get('https://www.onthemarket.com/async/search/properties/', params=params, headers=headers)
    r.raise_for_status()
    data = r.json()['properties']
    return data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above function accesses the OTM’s endpoint and returns data in JSON format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.route('/find', methods=['POST'])
def find_properties():
    refined_properties = []
    return_msg = {}
    try:
        form_data = request.form.to_dict()

        properties = search_properties(
            search_type=form_data['search-type'],
            location_id=form_data['location-id'],
            min_price=int(form_data['min-price']),
            max_price=int(form_data['max-price']),
            min_bedrooms=int(form_data['min-bedrooms']),
            property_type=form_data['prop-type']
        )

        for property in properties:
            if 'display_address' in property:
                address = property['display_address']
                price = property['price']
                property_link = property['property-link']
                image = property['cover-images']['default']
                refined_properties.append(
                    {'title': address,
                     'price': price,
                     'url': 'https://www.onthemarket.com{}'.format(property_link),
                     'image': image,
                     })
        return_msg = {'status': 'OK', 'msg': refined_properties}
    except Exception as ex:
        return_msg = {'status': 'FAIL', 'msg': str(ex)}
    finally:
        return jsonify(data=return_msg)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I iterate the records and just extract the required data points. You could connect OTM’s API directly, up to you. I found this way much better and cleaner. Anyways, our API is ready but you can’t connect it with VoiceFlow because it is running locally. So what’s the solution? Well, use &lt;a href="https://ngrok.com/download"&gt;ngrok&lt;/a&gt; for HTTP tunneling. After running the Flask app, I will just initiate &lt;em&gt;ngrok&lt;/em&gt; by using ngrok http 5000. Make sure your Flask app is already running. If all goes well you will see something like the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n3NQd4uL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ALFDMRct0Vh7OU0BE.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n3NQd4uL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ALFDMRct0Vh7OU0BE.png" alt="" width="300" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s check whether the API is working, head on to Postman, and test the POST request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JK48fiz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AsGU7Amx0q7jUKP9F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JK48fiz4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AsGU7Amx0q7jUKP9F.png" alt="" width="300" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it returned the required response&lt;/p&gt;

&lt;h3&gt;
  
  
  VoiceFlow Designer
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Creating Project and Adding a Greeting Node
&lt;/h4&gt;

&lt;p&gt;Alright, now it’s time to create our first chatbot. Assuming you are successfully registered, visit &lt;a href="https://creator.voiceflow.com/"&gt;https://creator.voiceflow.com/&lt;/a&gt; and hit the &lt;strong&gt;New Assistant&lt;/strong&gt; button. Once you do it, you will see a dialog box like the one below. Enter your bot details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AuwTpTtl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/274/0%2A-ZhArHIec6TL8H3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AuwTpTtl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/274/0%2A-ZhArHIec6TL8H3n.png" alt="" width="274" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open the designer first time it will appear like the below, select all and hit the delete button to clear the entire canvas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6E8oo5Zj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AX_SSvUkR2ou9GqZs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6E8oo5Zj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AX_SSvUkR2ou9GqZs.png" alt="" width="300" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Kbt4K3qA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AwS6Blt3iYR5ytPck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Kbt4K3qA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AwS6Blt3iYR5ytPck.png" alt="" width="300" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The very first thing I am going to do is to add a welcome message and then run the bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JLlfevWM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/0%2AaVVEtdNMtFt_zFgN.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JLlfevWM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/0%2AaVVEtdNMtFt_zFgN.gif" alt="" width="600" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I added a &lt;em&gt;Text Node&lt;/em&gt; for greetings and then gave it a test run after connecting the start node. There will always be an undeletable &lt;em&gt;start&lt;/em&gt; node. Cool, isn’t it?&lt;/p&gt;

&lt;p&gt;Now, before I move further, I want to let the bot know about the URL of my API endpoint. Since I prefer a configurable/modularized code, I will assign the base URI to a variable.&lt;/p&gt;

&lt;h4&gt;
  
  
  Variables
&lt;/h4&gt;

&lt;p&gt;VoiceFlow has a concept of &lt;em&gt;variables&lt;/em&gt;. If you want to work on VoiceFlow you must be well equipped with this concept. Variables in VoiceFlow can hold values that are available in other steps. There are multiple ways you can create a variable in VoiceFlow. The easiest way is to go to the section(Press &lt;em&gt;M&lt;/em&gt;) which opens a dialogue box like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TNK0rAYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AE4jEmu0xMw2qoNaT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TNK0rAYU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AE4jEmu0xMw2qoNaT.png" alt="" width="300" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What you see above are default or system variables offered by VoiceFlow. Let’s add a variable BASE_URI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--GbLLpSZa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/0%2AT2CCVm2LlzwVOTnj.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GbLLpSZa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/600/0%2AT2CCVm2LlzwVOTnj.gif" alt="" width="600" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The variable has been created but not initialized! You can either use the &lt;strong&gt;&lt;em&gt;Set&lt;/em&gt;&lt;/strong&gt; step to assign a variable or you can do it in JavaScript. Yes… VoiceFlow can manipulate things in JavaScript as well!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--egxEMN3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/302/0%2A4pdj5K1bTzndZkwN.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--egxEMN3K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/302/0%2A4pdj5K1bTzndZkwN.gif" alt="" width="302" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do note that I have added the URL within double quotes. VoiceFlow expects all strings within double quotes otherwise it does not set at all. VoiceFlow also allows you to debug variables which helps you understand how things are working. For clarity purposes, I am giving a static image of the debugging section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kQd4LwwH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/146/0%2ASzs978FBStNRnJv6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kQd4LwwH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/146/0%2ASzs978FBStNRnJv6.png" alt="" width="146" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, BASE_URI is set to &lt;em&gt;ngrok&lt;/em&gt; URL. The last_response variable contains the value returned by the chatbot. Though last_utterance is empty here, its value is set when a user enters his response. You can also use markdown syntax to format text, like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--J91nNAW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AzJhOJlR4mNhz1PYC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--J91nNAW6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AzJhOJlR4mNhz1PYC.png" alt="" width="300" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it will appear like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--O2GqhFYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/200/0%2AhE6VvK5JbGgjJ4Rp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--O2GqhFYm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/200/0%2AhE6VvK5JbGgjJ4Rp.png" alt="" width="200" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let’s add buttons for &lt;em&gt;Buy&lt;/em&gt; and &lt;em&gt;Rent&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ueBoy_Jl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/302/0%2Ans1BWpcHMPL99jcL.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ueBoy_Jl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/302/0%2Ans1BWpcHMPL99jcL.gif" alt="" width="302" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A couple of things are happening here: We are adding two buttons and then assigning a new variable search_type and then assigning values to it. These values will help to make the API call figure out whether someone wants to buy or seeking a property for rent. This is how buttons are rendered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gog-cQlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/217/0%2A0PXrGmieaMo6t6IY.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gog-cQlP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/217/0%2A0PXrGmieaMo6t6IY.png" alt="" width="217" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this is how they are rendered:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_xSKerb3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AQY4hrCWNOK6fN__4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_xSKerb3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AQY4hrCWNOK6fN__4.png" alt="" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice the search_type value now set to &lt;em&gt;for-sale&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  JavaScript and Buttons
&lt;/h4&gt;

&lt;p&gt;Now I want to let the user know what he opted for. One simple way is to just display the value behind the search_type value but it does not look good if you are setting non-human-friendly values. The best option is to display a value based on what he selected. For that purpose, we will be using the &lt;strong&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;/strong&gt; step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XmqUo6eN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/640/0%2AySqShGK0uvDt29Kg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XmqUo6eN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/640/0%2AySqShGK0uvDt29Kg.gif" alt="" width="640" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see we introduced a new variable search_type_text within JavaScript and then created in the VoiceFlow system in the &lt;em&gt;Text&lt;/em&gt; step. You could create the variable by going into the &lt;strong&gt;&lt;em&gt;Variables&lt;/em&gt;&lt;/strong&gt; section too. In either case, the variable must be created in VoiceFlow. The JavaScript step can not create a new VoiceFlow variable. Once it is created, you can display the formatted text in the bot. Next, we will select the desired location and store the selected value in location variable&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MXqgg-M8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A0AgzF8UpRBDTHO9Z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MXqgg-M8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A0AgzF8UpRBDTHO9Z.png" alt="" width="300" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whatever location is selected by the user, the info is stored in location a variable. Now we will be using the &lt;strong&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;/strong&gt; step again to format the selected location for the display.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--shHdMCKm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AEQL8dyRUmHrFRbLs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--shHdMCKm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AEQL8dyRUmHrFRbLs.png" alt="" width="300" height="165"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;BTW, you can assign a certain color to a block or set of blocks. For instance, I assigned a pinkish color to all steps that display variable values.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1ZqG6psz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2Ap6paWR_KCZDkfpGv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1ZqG6psz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2Ap6paWR_KCZDkfpGv.png" alt="" width="300" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Capture/Entities
&lt;/h4&gt;

&lt;p&gt;Now we need to fetch the user’s preferences for minimum, maximum price, and number of bedrooms. I will show for minimum price only because it is the same for others.&lt;/p&gt;

&lt;p&gt;Here I introduce the concept of &lt;strong&gt;&lt;em&gt;Entities&lt;/em&gt;&lt;/strong&gt;. Besides variables, VoiceFlow gives you the option to restrict the user input against a certain format. Here I am creating an entity min_price of the type Number . You can define your format as well but for our requirement, the number format is enough. It also supports, Name, Phone, Email, and a few other formats as well. Similarly, we will capture the value of max_price and no_of_bedrooms&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;&lt;em&gt;Capture&lt;/em&gt;&lt;/strong&gt; step has also an option of &lt;strong&gt;&lt;em&gt;No Match&lt;/em&gt;&lt;/strong&gt; which gets activated if the required data format is not found.&lt;/p&gt;

&lt;p&gt;Notice it asks for training when running the bot. It is because I added a new entity here. If things go wrong, it should ask to enter the minimum price again. One way is to connect the &lt;strong&gt;Invalid max price&lt;/strong&gt; block by connecting with the arrow back to the &lt;strong&gt;Select Minimum&lt;/strong&gt; block, another option is to use the &lt;em&gt;Action&lt;/em&gt; option to connect the blog which makes it a cleaner approach.&lt;/p&gt;

&lt;h4&gt;
  
  
  Condition
&lt;/h4&gt;

&lt;p&gt;VoiceFlow also provides you the option of adding a &lt;em&gt;condition,&lt;/em&gt; &lt;strong&gt;IF/ELSE&lt;/strong&gt; kind of thing_._ Adding a condition is pretty easy. All you have to do is to add a step.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xQb6nLGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ADKx8xXDvSm0e6k2D.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xQb6nLGI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ADKx8xXDvSm0e6k2D.png" alt="" width="300" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  API
&lt;/h4&gt;

&lt;p&gt;VoiceFlow gives you the facility to interact with 3rd party tools with the help of the &lt;strong&gt;&lt;em&gt;API&lt;/em&gt;&lt;/strong&gt; step. As the name suggests, this step is responsible for making an HTTP call and fetching the response for further action. In our case, it is to make the call to the API endpoint I introduced above.&lt;/p&gt;

&lt;p&gt;As you can see, after passing the required parameters it returned a JSON payload. Notice the returned data is changed if you change the searching criteria, sweet. Now the next step is to display the data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Carousel
&lt;/h4&gt;

&lt;p&gt;Carousel is one of the visual elements offered by VoiceFlow to show multiple items. This is how a carousel appears in the chatbot window:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jtmMwybm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/234/0%2AsdFbkbLHLXgJi01F.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jtmMwybm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/234/0%2AsdFbkbLHLXgJi01F.png" alt="" width="234" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But I want something else. I want to generate these carousel items dynamically and for that, we will be using &lt;a href="https://developer.voiceflow.com/docs/custom-actions-1"&gt;Custom Actions&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Custom Actions
&lt;/h4&gt;

&lt;p&gt;Custom Actions allow you to integrate 3rd party tools within VoiceFlow. It also allows you to render different VoiceFlow elements in JavaScript. First, you will create a custom action and you will name it a &lt;strong&gt;&lt;em&gt;carousel&lt;/em&gt;&lt;/strong&gt; and then you will add the following code in the &lt;strong&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;/strong&gt; step&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;selected_properties = []

carousel_dynamic = {
  layout:"Carousel",
  cards : []
}

function createCard(title, image, description) {
  let cardContent = {
    "title": title,
    "description": {
      "text": description
    },
    "imageUrl": image,
    "buttons": [
      {
        "name": "I am interested",
        "request": {
          "type": "property_selected",
          "payload": {
            title
          }
        }
      }
    ]
  };
  return cardContent;
}

for(let i=0;i&amp;lt; searched_properties.length;i++) {
  let GBPFormatter = new Intl.NumberFormat('en-US', {
  style: 'currency',
  currency: 'GBP',
  minimumFractionDigits: 0,
  maximumFractionDigits: 0
});

  carousel_dynamic.cards.push(createCard(searched_properties[i].title, searched_properties[i].image,searched_properties[i].price))  
}
// carousel_dynamic.cards.push(card,card)
// carousel_dynamic.cards.push(createCard('title', 'https://webbjenkins.imgix.net/PRA11696/images/apcc_PRA11696_IMG_00.jpg', 'description'))

carousel_dynamic = JSON.stringify(carousel_dynamic)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, this is not &lt;em&gt;exactly&lt;/em&gt; my code. I just refined the code given in one of the videos of VoiceFlow. Now, if you run this, this is how it would look like:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h2dKlqD5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/720/1%2AHXqlFr5c5pOOXhNnYzA-Qg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h2dKlqD5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/720/1%2AHXqlFr5c5pOOXhNnYzA-Qg.gif" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, it is generating carousel items at runtime with the help of &lt;strong&gt;&lt;em&gt;JavaScript&lt;/em&gt;&lt;/strong&gt; and the &lt;strong&gt;&lt;em&gt;Custom Action&lt;/em&gt;&lt;/strong&gt;  step.&lt;/p&gt;

&lt;p&gt;Now the next step is to capture contact details. It is the same as capturing min/maximum price and bedrooms. The captured data is sent via a POST call to the backend API and saved in a CSV which then is displayed on a page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MmO7D49Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2Acq3GaEYx-HhdtraW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MmO7D49Y--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2Acq3GaEYx-HhdtraW.png" alt="" width="300" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool! You can replace CSV with MySQL or any other DB, up to you. You can also shoot an email to both the potential client and the site Admin. You can also add the email to a newsletter so that you can send details of the new properties. There are endless possibilities. Now let’s give it a run from the start!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WbN4Gh9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/720/1%2AuAzxbw9gIxFYNwL0BK-quA.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WbN4Gh9O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://cdn-images-1.medium.com/max/720/1%2AuAzxbw9gIxFYNwL0BK-quA.gif" alt="" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Web Integration
&lt;/h4&gt;

&lt;p&gt;Now the bot is ready, it’s time to integrate it into your website. Click on the &lt;strong&gt;&lt;em&gt;Integration&lt;/em&gt;&lt;/strong&gt; option(Press &lt;strong&gt;5&lt;/strong&gt; ) on the Designer. When you open it you find 3 sections: &lt;strong&gt;Installation&lt;/strong&gt; , &lt;strong&gt;General&lt;/strong&gt; , and &lt;strong&gt;Appearance&lt;/strong&gt;. The first thing I am going to do is to install the widget on a web page but before you even do that, you have to publish your bot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NuV1VzXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AAv8euRg1arbqU7rQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NuV1VzXL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AAv8euRg1arbqU7rQ.png" alt="" width="300" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So head on to the D &lt;strong&gt;&lt;em&gt;esigner&lt;/em&gt;&lt;/strong&gt; option(Press &lt;strong&gt;1&lt;/strong&gt; ) and hit the &lt;strong&gt;&lt;em&gt;Publish&lt;/em&gt;&lt;/strong&gt; button. When you do it, it asks to version the bot which is optional.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wQ_KMHhr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AqkD3aZ5VDPYkvW5B.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wQ_KMHhr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AqkD3aZ5VDPYkvW5B.png" alt="" width="300" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a successful publish it asks to embed the widget which leads to the integration page I shown above. So I followed the instructions and put the chat widget on the page. I created a new endpoint, called Demo and put the code in it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d_j9d46a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A9LGRnhj00mEwp4Pa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d_j9d46a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A9LGRnhj00mEwp4Pa.png" alt="" width="300" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and here is the demo page endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@app.route('/demo', methods=['GET'])
def demo():
    return render_template('demo.html')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When I access this page it shows the chat window like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mBI6gmhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AFODEkYlbT5VpJ_8r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mBI6gmhI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AFODEkYlbT5VpJ_8r.png" alt="" width="300" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But…it does not look so good. How about adding some branding-related stuff and customizing it? First I will change the message: &lt;strong&gt;Starting Template — Webchat&lt;/strong&gt; in the &lt;strong&gt;_General _&lt;/strong&gt; section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--94rdHp6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AwtKfnvf1V3VFNQ63.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--94rdHp6K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AwtKfnvf1V3VFNQ63.png" alt="" width="300" height="233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will instantly reflect on the chat widget as soon as I do it. You can enable &lt;em&gt;Powered By&lt;/em&gt; Option if you want. After refreshing the page, the chat window looks like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---p4v5u0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/201/0%2AC504EtZW_dmoRhgQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---p4v5u0a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/201/0%2AC504EtZW_dmoRhgQ.png" alt="" width="201" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But it is not enough. I would like to change the color theme and icons. For that, I will open the &lt;strong&gt;&lt;em&gt;Appearance&lt;/em&gt;&lt;/strong&gt; section. After making changes, our bot will look like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IikpC1Oh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/210/0%2AVv7rH7Z8h-asiO0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IikpC1Oh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/210/0%2AVv7rH7Z8h-asiO0z.png" alt="" width="210" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Does it not look good? I matched the &lt;em&gt;OnTheMarket&lt;/em&gt; website color theme and used its icon here. Want to see this chatbot in action? Well, watch the demo video I shared above. One thing! &lt;strong&gt;&lt;em&gt;You must publish every time you make changes in the bot designer otherwise it will keep showing the old version.&lt;/em&gt;&lt;/strong&gt; Visit &lt;a href="https://learn.voiceflow.com/hc/en-us/articles/10569376208781"&gt;here&lt;/a&gt; to learn more about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, I gave you a beginner-level comprehensive overview of the VoiceFlow platform and how you can create a chatbot by leveraging it. It is a basic-level bot. You can customize it by adding more checks and validation or integrate some 3rd party CRM into it. So that’s it, the end of a very long post. Like always, the code along with the VoiceFlow . &lt;strong&gt;&lt;em&gt;vf&lt;/em&gt;&lt;/strong&gt; file is available on &lt;a href="https://github.com/kadnan/VoiceFlowLeadCapturingChatBot"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/create-your-first-real-estate-lead-capturing-chatbot-using-voiceflow-and-python-flask/"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on January 7, 2024.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>python</category>
      <category>chatbots</category>
    </item>
    <item>
      <title>Automate Your Finance Blog with WordPress and Google Bard in Python</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Sun, 24 Dec 2023 11:20:05 +0000</pubDate>
      <link>https://dev.to/kadnan/automate-your-finance-blog-with-wordpress-and-google-bard-in-python-7m8</link>
      <guid>https://dev.to/kadnan/automate-your-finance-blog-with-wordpress-and-google-bard-in-python-7m8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UfBOIKZb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AhN7mGPKwg2Feby6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UfBOIKZb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AhN7mGPKwg2Feby6x.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Generated by Leonardi.AI&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://blog.adnansiddiqi.me/create-stock-sentiment-analysis-in-python-using-chatgpt/"&gt;Earlier&lt;/a&gt; I gave you an overview of how you can you GPT APIs to build a stock sentiment analysis system. In this post, I am going to introduce you to Google Bard, Google’s answer to OpenAI’s chatGPT. Bard has been around for a few months but they recently offered APIs to access their LLM. Initially, they introduced &lt;a href="https://developers.googleblog.com/2023/03/announcing-palm-api-and-makersuite.html"&gt;PaLM APIs&lt;/a&gt; but very recently they have offered Gemini Pro and Gemini Pro Vision APIs which means that like GPT4 Vision, you can now use Bard APIs to process images. We are not going to discuss image processing capabilities at the moment. I am going to offer a use case where I will be using Gemini Pro APIs to create a daily stock market performance report and post it as an article on a WordPress blog using WordPress Rest APIs. The demo of the project is given below:&lt;/p&gt;

&lt;p&gt;Google is offering three different model sizes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--45ZOp1ZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AZbeXzUjdpO4x8Z6E.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--45ZOp1ZZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AZbeXzUjdpO4x8Z6E.png" alt="" width="300" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, I will give you a bit about how I will use &lt;a href="https://bard.google.com/"&gt;Google Bard&lt;/a&gt; to test the prompt, and later I will be using &lt;a href="https://ai.google.dev/"&gt;Gemini APIs&lt;/a&gt; to generate the blog post. At the end, I will be sending the generated content to the WordPress blog via API. Let’s start!&lt;/p&gt;
&lt;h3&gt;
  
  
  Writing Prompt
&lt;/h3&gt;

&lt;p&gt;Head on to Bard and write the below prompt:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Write me an article on stock market performance for the date 22 December 2023, including key indices such as the S&amp;amp;P 500, Dow Jones Industrial Average, and NASDAQ Composite. Highlight notable gainers and losers, identifying the sectors driving market movement. Discuss any significant economic events, corporate announcements, or geopolitical factors influencing market trends. Include information on trading volume, volatility, and any technical patterns observed. Additionally, comment on the overall market sentiment, investor behavior, and potential implications for the upcoming trading sessions. Lastly, offer insights into relevant commodities, currencies, and interest rates that may have impacted the broader financial landscape. Add relevant headings where needed. Also suggest relevant Blog post title in H1 tag. At the end return data in JSON format with two fields: Title and Description where the “Title” contains the blog title and “Desrcription” contains the entire article. Do not return any other text besides JSON&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After asking for the required piece of text I am asking to return the data in JSON format with the fields: &lt;em&gt;Title&lt;/em&gt; and &lt;em&gt;Description&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xisun7t5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A9wKiit2LA3cIb5ng.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xisun7t5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A9wKiit2LA3cIb5ng.png" alt="" width="300" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might find a slight change in the prompt I sent to Bard and the API itself because I had to tweak it to return the desired response via APIs. To Bard, I did not send, &lt;em&gt;Do not return any other text besides JSON&lt;/em&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Using Gemini APIs
&lt;/h3&gt;

&lt;p&gt;We have tested our prompt, and it’s time to integrate the prompt by using Gemini Pro APIs. To do that you will have to generate an API key first. Go to &lt;a href="https://makersuite.google.com/app/apikey"&gt;https://makersuite.google.com/app/apikey&lt;/a&gt; and create the API Key. Before testing the prompt itself, let’s see the different LLM models offered by Google.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import google.generativeai as genai
from dotenv import load_dotenv

if __name__ == ' __main__':
   load_dotenv()
   genai.configure(api_key=api_key)
   models = genai.list_models()
   for model in models:
     print(model.display_name, model.name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you run this code it outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PaLM 2 Chat (Legacy) models/chat-bison-001
PaLM 2 (Legacy) models/text-bison-001
Embedding Gecko models/embedding-gecko-001
Gemini Pro models/gemini-pro
Gemini Pro Vision models/gemini-pro-vision
Embedding 001 models/embedding-001
Model that performs Attributed Question Answering. models/aqa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this post, I am going to use Gemini Pro. Now let’s write the code using the prompt which will return the blog article in JSON format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json

import google.generativeai as genai
from dotenv import load_dotenv
import os
from datetime import datetime

def generate_article(stock_date):
    # Convert the string to a datetime object
    date_object = datetime.strptime(stock_date, "%Y-%m-%d")
    # Format the date
    formatted_date = date_object.strftime("%d %B %Y")
    load_dotenv()

    api_key = os.environ.get("GEMINI_API_KEY")
    prompt = f'Write me an article on stock market performance for the date {formatted_date}, including key indices such as the S&amp;amp;P 500, Dow Jones Industrial Average, and NASDAQ Composite. Highlight notable gainers and losers, identifying the sectors driving market movement. Discuss any significant economic events, corporate announcements, or geopolitical factors influencing market trends. Include information on trading volume, volatility, and any technical patterns observed. Additionally, comment on the overall market sentiment, investor behavior, and potential implications for the upcoming trading sessions. Lastly, offer insights into relevant commodities, currencies, and interest rates that may have impacted the broader financial landscape. Also suggest relevant Blog post title in H1 tag. At the end return data in JSON format with two fields: Title and Description where the "Title" contains the blog title and "Desrcription" contains the entire article. Do not return any other text besides JSON'
    genai.configure(api_key=api_key)
    model = genai.GenerativeModel("gemini-pro")
    response = model.generate_content(contents=prompt)
    response_text = response.text.replace("```

json", '').replace("

```", "")
    json_data = json.loads(response_text)
    return json_data

if __name__ == ' __main__':
    # Assuming you have a date string
    date_string = "2023-12-22"
    article = generate_article(date_string)
    print(article)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since I am writing the article on Sunday(24 December) and the market is closed, I have manually set the last Friday date here. Otherwise, the script will be working as a CRON job after market hours in working days and return the required data. As expected, when you run it, it generates the following JSON payload. I also had to sanitize the return output because the API often adds &lt;em&gt;“&lt;code&gt;json and “&lt;/code&gt;&lt;/em&gt; before and after the JSON payload.&lt;/p&gt;

&lt;p&gt;Anyways, we have done half of our work. Now we have to send this generated article to our WordPress blog.&lt;/p&gt;

&lt;p&gt;Download the latest version of WordPress from the website and install it on your machine. To enable the Markdown, you will have to install the &lt;a href="https://wordpress.org/plugins/markup-markdown/"&gt;Markup Markdown&lt;/a&gt; plugin. This plugin will disable the default editor and enable the Markdown editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DvUcHmkf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AQU7byOUXs-B33urq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DvUcHmkf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2AQU7byOUXs-B33urq.png" alt="" width="300" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cool, No?&lt;/p&gt;

&lt;h3&gt;
  
  
  WordPress REST APIs
&lt;/h3&gt;

&lt;p&gt;Now let’s test whether WordPress APIs are working or not. Before doing that, you have to change the format of permalink. The default format will not let you return the JSON data. I did something like the below, without doing this APIs will not work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xkIxw12d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ARJZ1wJPwXxvX4Ziw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xkIxw12d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2ARJZ1wJPwXxvX4Ziw.png" alt="" width="300" height="149"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s make a sample call to &lt;a href="http://localhost:8000/wp-json"&gt;&lt;strong&gt;http://localhost:8000/wp-json&lt;/strong&gt;&lt;/a&gt; and if all goes well you will see something like the below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pYsn9gyj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AwJwf1SVOeorZ0_up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pYsn9gyj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AwJwf1SVOeorZ0_up.png" alt="" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It returns a big JSON payload with all the details. The return of the JSON tells that the WordPress JSON API is working properly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using API to create posts
&lt;/h3&gt;

&lt;p&gt;Before creating or updating/deleting a post you must be authenticated as a WordPress user. WordPress provides a &lt;a href="https://github.com/WP-API/Basic-Auth"&gt;Basic Auth plugin&lt;/a&gt; to do this. Download the file and put it in the &lt;em&gt;plugins&lt;/em&gt; directory. Below is the code to create a post. You can check the docs to learn more about the &lt;a href="https://developer.wordpress.org/rest-api/reference/posts/#create-a-post"&gt;endpoint&lt;/a&gt; related to post creation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def create_post(title, text):
    article_url = ''

    headers = {
        'Content-Type': 'application/json',
    }

    json_data = {
        'title': title,
        'content': text,
        'status': 'publish',
    }
    if title != '' and text != '':
        r = requests.post('http://localhost:8000/wp-json/wp/v2/posts', headers=headers, json=json_data,
                          auth=('admin', 'admin'))
        if r.status_code == 201:
            article_url = r.json()['guid']['rendered']
    return article_url
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I am passing my user/password, in this case, &lt;em&gt;admin/admin&lt;/em&gt; for authentication purposes. For this very reason, I installed the authentication plugin. If all goes well, it will return the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ex_X_otG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AR-pqB92WbK8jGdp9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ex_X_otG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AR-pqB92WbK8jGdp9.png" alt="" width="800" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Want to see how it got rendered? here you go!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LevPVd9i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A4ef1ZVbP3FypeT2V.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LevPVd9i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A4ef1ZVbP3FypeT2V.png" alt="" width="300" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sweet, isn’t it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;So… in this post, you learned how you can leverage the power of LLMs to automate a blog in a certain niche. In our case, a finance blog. Currently, Gemini APIs have very limited access to the Internet but one does not always need real-time data. You can modify this prompt further to return high-volume keywords and then set them as &lt;em&gt;tags&lt;/em&gt; by using WordPress tags APIs. Like always, the code is available on &lt;a href="https://github.com/kadnan/FinanceBlogAutomationBardAPI"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Do you need to automate blogs using chatGPT or Google Bard APIs for your desired niche? let me know and I will create a system for you. Contact at &lt;a href="mailto:kadnan@gmail.com"&gt;kadnan@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/automate-your-finance-blog-with-wordpress-and-google-bard-in-python/"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on December 24, 2023.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>bardai</category>
      <category>python</category>
      <category>llm</category>
      <category>geminipro</category>
    </item>
    <item>
      <title>Using the RSI Indicator to Generate Trading Signals in Python with Ta-Lib</title>
      <dc:creator>Adnan Siddiqi</dc:creator>
      <pubDate>Fri, 24 Nov 2023 10:01:37 +0000</pubDate>
      <link>https://dev.to/kadnan/using-the-rsi-indicator-to-generate-trading-signals-in-python-with-ta-lib-30a5</link>
      <guid>https://dev.to/kadnan/using-the-rsi-indicator-to-generate-trading-signals-in-python-with-ta-lib-30a5</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1nEB4Y0q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMhbHgEGRGWilk9sT.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1nEB4Y0q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMhbHgEGRGWilk9sT.png" alt="" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post is the part of&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/tag/trading"&gt;&lt;em&gt;trading series&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the past, I gave you a &lt;a href="https://blog.adnansiddiqi.me/introduction-to-technical-analysis-in-python-using-ta-lib/"&gt;brief intro to Ta-Lib&lt;/a&gt; and how it can be used in technical analysis, in this post, I am going to discuss how you can RSI indicator to generate buy or sell signals in Python by using the TA-Lib library. Before I write code about the implementation, let’s discuss a bit about signal generation and RSI.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Are Signals
&lt;/h3&gt;

&lt;p&gt;In the world of trading, signals are cues or indicators that are derived from various kinds of analyses and guide investors on when to buy, sell, or hold shares. They help traders to make informed decisions based on market conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is A Technical Indicator
&lt;/h3&gt;

&lt;p&gt;A technical indicator in trading is a tool that helps investors analyze price trends and make decisions. It’s like a financial compass, providing insights into market behavior and helping traders identify potential opportunities or risks.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Is the RSI Indicator
&lt;/h3&gt;

&lt;p&gt;The RSI (Relative Strength Index) is a momentum oscillator that measures the speed and change of price movements. It ranges from &lt;strong&gt;0 to 100&lt;/strong&gt; and is used to identify &lt;em&gt;overbought&lt;/em&gt; or &lt;em&gt;oversold&lt;/em&gt; conditions in a market. An RSI level below &lt;strong&gt;30&lt;/strong&gt; generates buy signals while an RSI level above &lt;strong&gt;70&lt;/strong&gt; generates sell signals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation
&lt;/h3&gt;

&lt;p&gt;We discussed the main terminologies, now let’s write code for generating signals based on RSI values. I already discussed the development setup &lt;a href="https://blog.adnansiddiqi.me/introduction-to-technical-analysis-in-python-using-ta-lib/"&gt;here&lt;/a&gt; so you can refer to the previous article about it. One thing, unlike the earlier article where I used the “yfinance” API, I am using &lt;a href="https://www.alphavantage.co/"&gt;AlphaVantage&lt;/a&gt; APIs because for some reason &lt;em&gt;yfinance&lt;/em&gt; APIs are not working for me. On the other hand, Alphavantage provides awesome APIs which also have a free version. I am going to use the &lt;a href="https://www.alphavantage.co/documentation/#daily"&gt;endpoint&lt;/a&gt; that returns the daily data of a given symbol. All you have to do is to register for the free API KEY.&lt;/p&gt;

&lt;p&gt;So… the idea is, to get the daily data of a certain stock using AlphaVantage API and then use TaLib’s &lt;a href="https://hexdocs.pm/talib/TAlib.Indicators.RSI.html"&gt;RSI function&lt;/a&gt; to calculate RSI in a pandas dataframe using the default &lt;strong&gt;14-day&lt;/strong&gt; window. I am using jupyter notebook as it makes things easier. The very first thing is the import of libraries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# All Imports

from datetime import datetime as dt
import requests
import talib as ta
import pandas as pd
import matplotlib.pyplot as plt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next thing is using AlphaVantage’s API to get the OHLC data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def get_daily_ohlc_data(symbol):
    function_name = 'TIME_SERIES_DAILY'    
    base_url = 'https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&amp;amp;symbol={}&amp;amp;apikey={}'.format(symbol,API_KEY)
    r = requests.get(base_url)
    data = r.json()["Time Series (Daily)"]
    return data

ohlc = get_daily_ohlc_data("MSFT")
# Convert to DataFrame
df = pd.DataFrame.from_dict(ohlc, orient="index")
# Rename columns
df = df.rename(columns={
"1. open": "open",
"2. high": "high",
"3. low": "low",
"4. close": "close",
"5. volume": "volume"
})
df = df.apply(pd.to_numeric)
df = df.sort_index(ascending=True)
df
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function is pretty simple. Using &lt;em&gt;requests&lt;/em&gt; library to call the &lt;a href="https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&amp;amp;symbol=IBM&amp;amp;apikey=demo"&gt;API&lt;/a&gt; and then accessing the relevant dict’s key to fetch OHLC data of Microsoft’s stock. After that, convert the payload into a pandas dataframe. Renaming of columns to make it more readable, after that, I am soring them out in ascending order so that I get the latest records at the bottom. When you do that, you will get something like the below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--crhf0Myc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A3K6Gp4RIg5vQgfvX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--crhf0Myc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/300/0%2A3K6Gp4RIg5vQgfvX.png" alt="" width="300" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, our required dataframe is available, what is left now to calculate RSI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def generate_rsi_signals(data, period=14, overbought_threshold=70, oversold_threshold=30):

    # Calculate RSI
    data['RSI'] = ta.RSI(data['close'], timeperiod=period)

    # Initialize 'Signal' column with 'Neutral'
    data['Signal'] = 'Neutral'

    # Generate signals
    data.loc[data['RSI'] &amp;lt; oversold_threshold, 'Signal'] = 'Buy'
    data.loc[data['RSI'] &amp;gt; overbought_threshold, 'Signal'] = 'Sell'

    return data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order to calculate RSI, you need to assign a window period, the default value is  &lt;strong&gt;14.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the context of the Relative Strength Index (RSI), the parameter period refers to the number of historical price points used in the calculation. The RSI is a momentum oscillator that measures the speed and change of price movements. The formula for calculating RSI involves comparing the magnitude of recent gains to recent losses over a specified time period.&lt;/p&gt;

&lt;p&gt;So, calling &lt;a href="https://hexdocs.pm/talib/TAlib.Indicators.RSI.html"&gt;TALIb’s RSI function&lt;/a&gt; for the period of &lt;strong&gt;14&lt;/strong&gt; , we add another column in our dataframe, named,  &lt;strong&gt;RSI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RSI is calculated but things do not end here, the next thing we have to do is to generate signals: &lt;em&gt;Buy&lt;/em&gt;, &lt;em&gt;Sell,&lt;/em&gt; and &lt;em&gt;Neutral.&lt;/em&gt; Then the threshold’s value is to generate buy or sell signals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;df_rsi = generate_rsi_signals(df)
df_rsi.tail(17)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the above function is called and fetches the last 15 or 17 values, you will get a dataframe like the one below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pmt9CE8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ar1c2SGEVYRTPbOui.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pmt9CE8Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2Ar1c2SGEVYRTPbOui.png" alt="" width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it generated different signals over the period of time, it generated a sell signal where the RSI was more than 70 otherwise neutral. Usually, when you create a trading bot that runs all the time during trading hours, you pick the very last value to decide whether you wanna buy, sell, or hold. Here, the very last value is &lt;em&gt;Neutral&lt;/em&gt; or hold thus we will not take any action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Do you have some profitable strategy that you want to automate that trade on your behalf without any intervention? I can help you in this regard. Whether it’s a stock bot, crypto bot, or forex, I can write the code to run and trade based on your strategy. Contact me at kadnan @ gmail.com&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this post, you learned how easily you can access stock data and then calculate RSI for generating buy and sell signals and minting money ????&lt;/p&gt;

&lt;p&gt;Like always, the code is available on &lt;a href="https://github.com/kadnan/IntroTechnicalAnalysis"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at&lt;/em&gt; &lt;a href="https://blog.adnansiddiqi.me/using-the-rsi-indicator-to-generate-trading-signals-in-python-with-talib/"&gt;&lt;em&gt;https://blog.adnansiddiqi.me&lt;/em&gt;&lt;/a&gt; &lt;em&gt;on November 24, 2023.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>rsiindicator</category>
      <category>algorithmictrading</category>
      <category>tutorial</category>
      <category>python</category>
    </item>
  </channel>
</rss>
