<?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: Suman Debnath</title>
    <description>The latest articles on DEV Community by Suman Debnath (@debnsuma).</description>
    <link>https://dev.to/debnsuma</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%2F281052%2F696d68b0-587b-4736-ba2a-9264af5d0536.jpeg</url>
      <title>DEV Community: Suman Debnath</title>
      <link>https://dev.to/debnsuma</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/debnsuma"/>
    <language>en</language>
    <item>
      <title>Creating Software Teams with AI Agents and Bedrock</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Mon, 28 Apr 2025 21:24:29 +0000</pubDate>
      <link>https://dev.to/aws/code-without-coding-creating-software-teams-with-ai-agents-and-bedrock-539i</link>
      <guid>https://dev.to/aws/code-without-coding-creating-software-teams-with-ai-agents-and-bedrock-539i</guid>
      <description>&lt;p&gt;Imagine having a complete engineering team at your fingertips - an engineering lead, a backend developer, a frontend engineer, and a test engineer - all working in perfect harmony to build your application. Now imagine this entire team is powered by AI. &lt;/p&gt;

&lt;p&gt;In this blog post, I'll walk you through building an AI-powered engineering team using CrewAI and Amazon Bedrock to develop a stock management application. Let's turn this sci-fi concept into reality!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CrewAI?
&lt;/h2&gt;

&lt;p&gt;CrewAI is a game-changing open-source framework that lets you create a team of specialized AI agents working together on complex projects. Unlike traditional single-agent approaches, CrewAI mimics how human teams operate - with different specialists handling specific aspects of a project.&lt;/p&gt;

&lt;p&gt;Think of it as assembling your dream engineering team, where each AI agent brings unique skills to the table:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The visionary Engineering Lead&lt;/strong&gt; creates detailed designs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The meticulous Backend Engineer&lt;/strong&gt; writes clean, efficient code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The creative Frontend Engineer&lt;/strong&gt; crafts intuitive user interfaces&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The thorough Test Engineer&lt;/strong&gt; ensures everything works perfectly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Our Mission: Build a Stock Management App
&lt;/h2&gt;

&lt;p&gt;Our AI team will build a comprehensive stock management application that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manages user accounts and funds&lt;/li&gt;
&lt;li&gt;Handles buying and selling of shares&lt;/li&gt;
&lt;li&gt;Tracks portfolio value and calculates profits/losses&lt;/li&gt;
&lt;li&gt;Enforces sensible constraints (no overdrafts or overselling)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dive into how we'll make this happen!&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup: The Skeleton of Our AI Team
&lt;/h2&gt;

&lt;p&gt;Before we write a single line of code, let's understand the architecture of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;engineering_team/
├── config/
│   ├── agents.yaml  (Defines our AI team members)
│   └── tasks.yaml   (Specifies what each team member will do)
├── output/          (Where our finished application will go)
├── src/
│   ├── crew.py      (Orchestrates team collaboration)
│   └── main.py      (Starting point for our project)
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each file plays a crucial role in bringing our AI team to life.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Setup in 3 Easy Steps
&lt;/h2&gt;

&lt;p&gt;Let's roll up our sleeves and get started:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install the essentials
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install uv (a faster Python package installer)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-LsSf&lt;/span&gt; https://astral.sh/uv/install.sh | sh

&lt;span class="c"&gt;# Verify installation&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;uv &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# Install CrewAI&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;uv tool &lt;span class="nb"&gt;install &lt;/span&gt;crewai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Create your AI crew
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;crewai create my_engg_team
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, select Amazon Bedrock as your provider and choose Claude 3.5 Sonnet as your model. You'll need to provide your AWS credentials to access these powerful models.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Configure your team
&lt;/h3&gt;

&lt;p&gt;Now comes the fun part - defining our AI team members and their responsibilities!&lt;/p&gt;

&lt;h2&gt;
  
  
  The Dream Team: Configuring Our AI Engineers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Engineering Lead (agents.yaml)
&lt;/h3&gt;

&lt;p&gt;Our engineering lead takes high-level requirements and turns them into detailed designs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;engineering_lead&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Engineering Lead for the engineering team, directing the work of the engineer&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Take the high level requirements described here and prepare a detailed design for the backend developer;&lt;/span&gt;
    &lt;span class="s"&gt;everything should be in 1 python module; describe the function and method signatures in the module.&lt;/span&gt;
    &lt;span class="s"&gt;The python module must be completely self-contained, and ready so that it can be tested or have a simple UI built for it.&lt;/span&gt;
    &lt;span class="s"&gt;Here are the requirements: {requirements}&lt;/span&gt;
    &lt;span class="s"&gt;The module should be named {module_name} and the class should be named {class_name}&lt;/span&gt;
  &lt;span class="na"&gt;backstory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;You're a seasoned engineering lead with a knack for writing clear and concise designs.&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0&lt;/span&gt;

&lt;span class="na"&gt;backend_engineer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Python Engineer who can write code to achieve the design described by the engineering lead&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Write a python module that implements the design described by the engineering lead, in order to achieve the requirements.&lt;/span&gt;
    &lt;span class="s"&gt;The python module must be completely self-contained, and ready so that it can be tested or have a simple UI built for it.&lt;/span&gt;
    &lt;span class="s"&gt;Here are the requirements: {requirements}&lt;/span&gt;
    &lt;span class="s"&gt;The module should be named {module_name} and the class should be named {class_name}&lt;/span&gt;
  &lt;span class="na"&gt;backstory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;You're a seasoned python engineer with a knack for writing clean, efficient code.&lt;/span&gt;
    &lt;span class="s"&gt;You follow the design instructions carefully.&lt;/span&gt;
    &lt;span class="s"&gt;You produce 1 python module named {module_name} that implements the design and achieves the requirements.&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0&lt;/span&gt;

&lt;span class="na"&gt;frontend_engineer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;A Gradio expert to who can write a simple frontend to demonstrate a backend&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Write a gradio UI that demonstrates the given backend, all in one file to be in the same directory as the backend module {module_name}.&lt;/span&gt;
    &lt;span class="s"&gt;Here are the requirements: {requirements}.&lt;/span&gt;
  &lt;span class="na"&gt;backstory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;You're a seasoned python engineer highly skilled at writing simple Gradio UIs for a backend class.&lt;/span&gt;
    &lt;span class="s"&gt;You produce a simple gradio UI that demonstrates the given backend class; you write the gradio UI in a module app.py that is in the same directory as the backend module {module_name}.&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0&lt;/span&gt;

&lt;span class="na"&gt;test_engineer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;An engineer with python coding skills who can write unit tests for the given backend module {module_name}&lt;/span&gt;
  &lt;span class="na"&gt;goal&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;Write unit tests for the given backend module {module_name} and create a test_{module_name} in the same directory as the backend module.&lt;/span&gt;
  &lt;span class="na"&gt;backstory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="s"&gt;You're a seasoned QA engineer and software developer who writes great unit tests for python code.&lt;/span&gt;
  &lt;span class="na"&gt;llm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bedrock/anthropic.claude-3-5-sonnet-20240620-v1:0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each agent configuration includes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role:&lt;/strong&gt; Describes the agent's position in the team&lt;br&gt;
&lt;strong&gt;Goal:&lt;/strong&gt; Specifies what the agent needs to accomplish&lt;br&gt;
&lt;strong&gt;Backstory:&lt;/strong&gt; Provides context that shapes the agent's approach&lt;br&gt;
&lt;strong&gt;LLM:&lt;/strong&gt; Specifies which language model powers the agent (in this case, Claude 3.5 Sonnet via Amazon Bedrock)&lt;/p&gt;

&lt;p&gt;Our team includes four agents, each serving a distinct role:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Engineering Lead:&lt;/strong&gt; Creates detailed design specifications&lt;br&gt;
&lt;strong&gt;Backend Engineer:&lt;/strong&gt; Implements the core functionality in Python&lt;br&gt;
&lt;strong&gt;Frontend Engineer:&lt;/strong&gt; Develops a Gradio-based UI&lt;br&gt;
&lt;strong&gt;Test Engineer:&lt;/strong&gt; Writes unit tests for quality assurance&lt;/p&gt;
&lt;h3&gt;
  
  
  Assigning Tasks (tasks.yaml)
&lt;/h3&gt;

&lt;p&gt;Each team member needs clear instructions on what to do:&lt;/p&gt;
&lt;h3&gt;
  
  
  Crew Definition (&lt;code&gt;crew.py&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;crew.py&lt;/code&gt; file organizes the agents and tasks into a cohesive team:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crewai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crewai.project&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CrewBase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;

&lt;span class="c1"&gt;# If you want to run a snippet of code before or after the crew starts,
# you can use the @before_kickoff and @after_kickoff decorators
# https://docs.crewai.com/concepts/crews#example-crew-class-with-decorators
&lt;/span&gt;
&lt;span class="nd"&gt;@CrewBase&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyEnggTeam&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;EngineeringTeam3 crew&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;agents_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;config/agents.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;tasks_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;config/tasks.yaml&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="nd"&gt;@agent&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;engineering_lead&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;engineering_lead&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@agent&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;backend_engineer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;backend_engineer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;allow_code_execution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code_execution_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;safe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Uses Docker for safety
&lt;/span&gt;            &lt;span class="n"&gt;max_execution_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;max_retry_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; 
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@agent&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;frontend_engineer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;frontend_engineer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@agent&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_engineer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test_engineer&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;allow_code_execution&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;code_execution_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;safe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Uses Docker for safety
&lt;/span&gt;            &lt;span class="n"&gt;max_execution_time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
            &lt;span class="n"&gt;max_retry_limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; 
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;design_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;design_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;code_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;code_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;frontend_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;frontend_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;test_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;   

    &lt;span class="nd"&gt;@crew&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&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;Crew&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Creates the research crew&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Starting Gun (main.py)
&lt;/h3&gt;

&lt;p&gt;Finally, we kick off the development process:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env python
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;warnings&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;my_engg_team.crew&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MyEnggTeam&lt;/span&gt;

&lt;span class="n"&gt;warnings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filterwarnings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ignore&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;category&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;SyntaxWarning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pysbd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Disable only CrewAI telemetry
&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;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;CREWAI_DISABLE_TELEMETRY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Disable all OpenTelemetry (including CrewAI)
&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;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OTEL_SDK_DISABLED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# Create output directory if it doesn't exist
&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;output&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;requirements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
A simple account management system for a trading simulation platform.
The system should allow users to create an account, deposit funds, and withdraw funds.
The system should allow users to record that they have bought or sold shares, providing a quantity.
The system should calculate the total value of the user&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s portfolio, and the profit or loss from the initial deposit.
The system should be able to report the holdings of the user at any point in time.
The system should be able to report the profit or loss of the user at any point in time.
The system should be able to list the transactions that the user has made over time.
The system should prevent the user from withdrawing funds that would leave them with a negative balance, or
 from buying more shares than they can afford, or selling shares that they don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t have.
 The system has access to a function get_share_price(symbol) which returns the current price of a share, and includes a test implementation that returns fixed prices for AAPL, TSLA, GOOGL.
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
&lt;span class="n"&gt;module_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accounts.py&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;class_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Account&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Run the research crew.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;inputs&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;requirements&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;requirements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;module_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;module_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;class_name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;class_name&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# Create and run the crew
&lt;/span&gt;    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyEnggTeam&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;kickoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;inputs&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;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Showtime! Watching AI Engineers in Action
&lt;/h2&gt;

&lt;p&gt;With everything set up, it's time to see our AI team in action:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;crewai run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now sit back and watch as your AI engineering team springs to life! You'll see a cascade of activity:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;Engineering Lead&lt;/strong&gt; analyzes the requirements and crafts a detailed design&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Backend Engineer&lt;/strong&gt; takes that design and implements it in clean Python code&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Frontend Engineer&lt;/strong&gt; creates a user-friendly Gradio interface&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;Test Engineer&lt;/strong&gt; ensures everything works as expected with comprehensive tests&lt;/li&gt;
&lt;/ol&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%2Fg7pvwmgbwwwpc6yhn5cc.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%2Fg7pvwmgbwwwpc6yhn5cc.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&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%2Fux9avmwb90p7mz5okwsj.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%2Fux9avmwb90p7mz5okwsj.png" alt=" " width="800" height="804"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Grand Finale: Running Our Application
&lt;/h2&gt;

&lt;p&gt;Once the AI team finishes their work, we can actually run the application they built:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;output
&lt;span class="nv"&gt;$ &lt;/span&gt;uv run app.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà! A fully functional stock management application appears:&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%2Fpkkqyvklyduyee7i2pr6.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%2Fpkkqyvklyduyee7i2pr6.png" alt=" " width="800" height="805"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now deposit funds, buy and sell stocks, track your portfolio value, and more - all created by an AI engineering team!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Just Happened? Behind the Scenes
&lt;/h2&gt;

&lt;p&gt;Let's take a moment to appreciate what just happened:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Design Phase&lt;/strong&gt;: Our AI Engineering Lead analyzed requirements and created a detailed blueprint&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Implementation Phase&lt;/strong&gt;: The Backend Engineer wrote clean, functional Python code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UI Development&lt;/strong&gt;: The Frontend Engineer built an intuitive Gradio interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality Assurance&lt;/strong&gt;: The Test Engineer ensured everything worked correctly&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All of this happened with minimal human intervention - just a few configuration files and a press of a button!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is Revolutionary
&lt;/h2&gt;

&lt;p&gt;This approach to software development is groundbreaking for several reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: Development that would take days or weeks happens in minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Specialization&lt;/strong&gt;: Each agent brings focused expertise to their specific role&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration&lt;/strong&gt;: Information flows naturally between team members&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality&lt;/strong&gt;: The test-driven approach ensures robust, working software&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility&lt;/strong&gt;: Complex applications can be built even if you're not a coding expert&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Future of Development?
&lt;/h2&gt;

&lt;p&gt;Will AI teams replace human developers? Not likely. But they will transform how we work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rapid Prototyping&lt;/strong&gt;: Test ideas and build MVPs in record time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Skill Augmentation&lt;/strong&gt;: Fill gaps in your human team's expertise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;24/7 Development&lt;/strong&gt;: Your AI team never sleeps (or needs coffee breaks!)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning Tool&lt;/strong&gt;: Watch experts at work and learn best practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;The possibilities are endless! You could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Expand the team with more specialized roles (DevOps engineer, security specialist)&lt;/li&gt;
&lt;li&gt;Tackle more complex applications&lt;/li&gt;
&lt;li&gt;Customize the agents with domain-specific knowledge&lt;/li&gt;
&lt;li&gt;Integrate with your existing development workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building an AI engineering team with CrewAI and Amazon Bedrock demonstrates how far AI has come. We've moved from AI assistants that can answer questions to AI teams that can build entire applications from scratch.&lt;/p&gt;

&lt;p&gt;This approach doesn't replace human creativity and innovation - it amplifies it. By handling routine implementation details, AI engineering teams free human developers to focus on the bigger picture: solving real-world problems and creating value.&lt;/p&gt;

&lt;p&gt;So, are you ready to assemble your AI engineering dream team? The tools are here, and the possibilities are limitless!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>crewai</category>
      <category>bedrock</category>
    </item>
    <item>
      <title>Standardizing AI Tooling with Model Context Protocol (MCP)</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Wed, 09 Apr 2025 13:15:20 +0000</pubDate>
      <link>https://dev.to/aws/standardizing-ai-tooling-with-model-context-protocol-mcp-nmj</link>
      <guid>https://dev.to/aws/standardizing-ai-tooling-with-model-context-protocol-mcp-nmj</guid>
      <description>&lt;h1&gt;
  
  
  What is Model Context Protocol (MCP) ?
&lt;/h1&gt;

&lt;p&gt;MCP is like a USB-C port for your AI applications.&lt;/p&gt;

&lt;p&gt;Just as USB-C offers a standardized way to connect devices to various accessories, MCP standardizes how your AI apps connect to different data sources and tools.&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%2Fk5xfqwv7v42tu5bdrane.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%2Fk5xfqwv7v42tu5bdrane.png" alt=" " width="659" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  MCP Architecture
&lt;/h1&gt;

&lt;p&gt;At its core, MCP follows a client-server architecture where a host application can connect to multiple servers.&lt;/p&gt;

&lt;p&gt;It has three key components: &lt;/p&gt;

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

2. Client

3. Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F7lr9tmc9rnl5f96coirf.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%2F7lr9tmc9rnl5f96coirf.png" alt=" " width="800" height="776"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Host&lt;/strong&gt; represents any AI app (Claude desktop, Cursor) that provides an environment for AI interactions, accesses tools and data, and runs the MCP Client. The host manages the AI model and runs the MCP Client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Client&lt;/strong&gt; within the host and facilitates communication with MCP servers. It's responsible for discovering server capabilities and transmitting messages between the host and servers.&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%2Fn17ox4of42vzqtgba1qy.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%2Fn17ox4of42vzqtgba1qy.png" alt=" " width="730" height="478"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MCP Server exposes specific capabilities and provides access to data, like,&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%2F177wuhfengk0fzdmlrm4.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%2F177wuhfengk0fzdmlrm4.png" alt=" " width="766" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How MCP Works ?
&lt;/h1&gt;

&lt;p&gt;Understanding client-server communication is essential for building your own MCP client-server.&lt;/p&gt;

&lt;p&gt;Let's see how MCP communication flows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Discovery Phase:&lt;/strong&gt; The client queries the server to learn its capabilities&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Capability Exchange:&lt;/strong&gt; The server shares what it can do&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Acknowledgment:&lt;/strong&gt; The client confirms successful connection&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ongoing Communication:&lt;/strong&gt; Messages flow between client and server&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%2Fjb1l5oe1rbjw9saidpxy.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%2Fjb1l5oe1rbjw9saidpxy.png" alt=" " width="726" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Real-World Example: Smart Home Integration
&lt;/h1&gt;

&lt;p&gt;Let's illustrate MCP with a practical example comparing traditional API integration with MCP for a smart home system:&lt;/p&gt;

&lt;h2&gt;
  
  
  Traditional API Approach:
&lt;/h2&gt;

&lt;p&gt;You build a voice assistant that integrates with your smart lighting system. &lt;br&gt;
Initially, your lighting API accepts two parameters:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- room (which room to control)
- state (on/off)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You hardcode your assistant to send requests with these exact parameters.&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%2F2rvnzhbuile3cay7ame9.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%2F2rvnzhbuile3cay7ame9.png" alt=" " width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Later, the lighting system company updates their API to require a third required parameter:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- brightness (light intensity)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Suddenly, your voice assistant stops working correctly because your code doesn't include this new required parameter. &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%2Fweojy2wn4j17j7px8lss.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%2Fweojy2wn4j17j7px8lss.png" alt=" " width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  MCP Approach:
&lt;/h2&gt;

&lt;p&gt;Your voice assistant (MCP Host) connects to your smart lighting system (MCP Server).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- The assistant asks: "What commands do you support?"

- The lighting system responds: "I support controlling lights with room and state parameters."

- The assistant works with these parameters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fy0jiwuxe1l72upwqlugd.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%2Fy0jiwuxe1l72upwqlugd.png" alt=" " width="798" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the lighting company updates their system:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- The assistant asks again: "What commands do you support?"

- The lighting system now responds: "I support controlling lights with room, state, and brightness parameters."

- The assistant automatically adapts to include this new parameter in its requests.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;No code changes needed! Your assistant continues to work flawlessly.&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%2Fn7osqgjj5nkqric4oiv7.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%2Fn7osqgjj5nkqric4oiv7.png" alt=" " width="743" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;MCP is more than just a technical spec, it's a bridge that enables seamless, future-proof connections between AI applications and evolving tools or data sources. By abstracting away brittle integrations and fostering adaptability, MCP is paving the way for more robust, modular, and intelligent AI systems.&lt;/p&gt;

&lt;p&gt;Just like USB-C simplified hardware connections, MCP simplifies AI interoperability.&lt;/p&gt;

&lt;p&gt;To learn more you can check here: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/blogs/machine-learning/introducing-aws-mcp-servers-for-code-assistants-part-1/?trk=7dd6ab1d-561b-49c6-bae9-b5978e1e2073&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Introducing AWS MCP Servers for code assistants&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/awslabs/mcp/?trk=7dd6ab1d-561b-49c6-bae9-b5978e1e2073&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;AWS MCP Servers&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>agents</category>
      <category>genai</category>
    </item>
    <item>
      <title>Integrating Vision-Language Models into Agentic RAG Systems with ColPali</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Mon, 31 Mar 2025 21:33:26 +0000</pubDate>
      <link>https://dev.to/aws/beyond-text-building-intelligent-document-agents-with-vision-language-models-and-colpali-and-oc</link>
      <guid>https://dev.to/aws/beyond-text-building-intelligent-document-agents-with-vision-language-models-and-colpali-and-oc</guid>
      <description>&lt;p&gt;In this tutorial, we will walk through a relatively new technique to build a RAG based pipeline using vision based model, which is based on a paper called &lt;a href="https://arxiv.org/abs/2407.01449" rel="noopener noreferrer"&gt;ColPali&lt;/a&gt; (published in June 2024). In the rapidly evolving world of AI, we're constantly seeking more natural ways for machines to understand and process information. Traditional RAG based systems have been transformative, but they often struggle with multimodal content (i.e. documents that contains a mix of text, images, tables, and more). &lt;/p&gt;

&lt;p&gt;Before we dive into this new vision-based retrieval technique, it's worth briefly revisiting the challenges faced by traditional RAG systems when dealing with multimodal data. This context will help us better appreciate the value that a vision-based retrieval model like ColPali offers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge with Traditional RAG
&lt;/h2&gt;

&lt;p&gt;Imagine you're trying to find information in a textbook that contains diagrams, charts, equations, and text. The traditional RAG approach would typically require:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extracting text from the document&lt;/li&gt;
&lt;li&gt;Processing images separately&lt;/li&gt;
&lt;li&gt;Processing tables separately&lt;/li&gt;
&lt;li&gt;Trying to understand tables in isolation&lt;/li&gt;
&lt;li&gt;Somehow stitching all this information together&lt;/li&gt;
&lt;/ol&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%2Fiphvgo17azw8qkeah27t.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%2Fiphvgo17azw8qkeah27t.png" alt=" " width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This fragmented approach &lt;strong&gt;loses vital context&lt;/strong&gt;. A diagram often explains concepts that would take paragraphs of text, and the layout of information itself can convey meaning. When working with educational content, research papers, or technical documentation, this limitation becomes particularly problematic.&lt;/p&gt;

&lt;p&gt;Traditional RAG systems struggle with this. Extracting text from visuals and then feeding it into an LLM &lt;strong&gt;strips away structural nuances&lt;/strong&gt;. But what if we could process raw visual documents directly and retrieve information based on &lt;strong&gt;visual relevance&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;That’s exactly what &lt;strong&gt;ColPali&lt;/strong&gt; enables.&lt;/p&gt;

&lt;h2&gt;
  
  
  ColPali: Efficient Document Retrieval with Vision Language Models
&lt;/h2&gt;

&lt;p&gt;Vision-driven RAG systems tackle this challenge differently. Instead of breaking a document into separate components, they process pages &lt;strong&gt;as they appear visually,&lt;/strong&gt; just like humans do when reading. This approach &lt;strong&gt;preserves spatial relationships and visual context&lt;/strong&gt;, both of which are often essential for deep understanding.&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%2F5psrcmfopx3x6t8vqepa.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%2F5psrcmfopx3x6t8vqepa.png" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ColPali uses vision-language models (VLMs) to enhance document processing, bypassing traditional text extraction steps and directly analyzing documents as they are. &lt;/p&gt;

&lt;p&gt;In this tutorial, we'll explore how to build such a system using:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;ColPali&lt;/strong&gt; - A multimodal document retrieval model that processes documents visually [for retrieval]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Nova&lt;/strong&gt; - A powerful vision language model for analyzing retrieved content [for generation]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CrewAI&lt;/strong&gt; - An agent framework for orchestrating complex AI workflows[for building the Agentic RAG based system]&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's break down how this system works.&lt;/p&gt;

&lt;h2&gt;
  
  
  How ColPali Enhances Document Understanding
&lt;/h2&gt;

&lt;p&gt;At its core, &lt;strong&gt;ColPali&lt;/strong&gt; transforms each page of a document into an &lt;strong&gt;embedding&lt;/strong&gt;, similar to how &lt;a href="https://openai.com/index/clip/" rel="noopener noreferrer"&gt;CLIP&lt;/a&gt; does for images, but optimized for documents. It views each page holistically through a vision-language model. Here's how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Patch Creation&lt;/strong&gt;: Documents are divided into manageable image patches, simplifying complex page layouts into smaller, processable units.&lt;/li&gt;
&lt;/ol&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%2Fm2r0uxtk5b45mt8sdzag.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%2Fm2r0uxtk5b45mt8sdzag.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Generating Brain Food&lt;/strong&gt;: Each patch is converted into embeddings, rich numerical representations that capture both visual and contextual data. These embeddings serve as the foundation for understanding and retrieving relevant content.&lt;/li&gt;
&lt;/ol&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%2Fzykdc8mls8gr8n5ii3jb.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%2Fzykdc8mls8gr8n5ii3jb.png" alt=" " width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Detour of Vision Language Model (VLM)
&lt;/h2&gt;

&lt;p&gt;To fully grasp how &lt;strong&gt;ColPali&lt;/strong&gt; handles embedding generation, it’s essential to understand &lt;strong&gt;Vision-Language Models (VLMs),&lt;/strong&gt; models that excel at integrating &lt;strong&gt;visual data&lt;/strong&gt; with &lt;strong&gt;textual annotations&lt;/strong&gt;. For a deep dive into VLMs, refer to &lt;a href="https://github.com/debnsuma/fcc-ai-engineering-aws/blob/main/02-multimodal-llm/00_Introduction_MultimodalLLM.ipynb" rel="noopener noreferrer"&gt;tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At a high level, VLM consist of the following key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Image Encoder&lt;/strong&gt;: Breaks down images into patches and encodes each one into embeddings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text Encoder&lt;/strong&gt;: Simultaneously encodes any accompanying text into its own set of embeddings, preserving language-specific context.&lt;/li&gt;
&lt;/ul&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%2Fkqegr5kjfdywla10hxjb.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%2Fkqegr5kjfdywla10hxjb.png" alt=" " width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Image Encoder&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The Image Encoder component of a VLM breaks down images into smaller patches and processes each patch individually to generate embeddings. These embeddings represent the visual content in a format that the model can interpret and reason over.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Patch Processing&lt;/strong&gt;: Images are divided into patches, which are then individually fed into the encoder. This modular approach allows the model to focus on detailed aspects of each image segment, facilitating a deeper understanding of the overall visual content.&lt;/li&gt;
&lt;/ul&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%2F7mw2poul2wh2bciivciu.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%2F7mw2poul2wh2bciivciu.png" alt=" " width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Adapter Layer Transformation&lt;/strong&gt;: After encoding, the output from the image encoder passes through an adapter layer. This layer converts the visual embeddings into a numerical format optimized for further processing within the model.&lt;/li&gt;
&lt;/ul&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%2Fz92bqo5ool47xt4bp4hy.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%2Fz92bqo5ool47xt4bp4hy.png" alt=" " width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Text Encoder&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Parallel to the image encoding, the Text Encoder processes textual data. It converts text into a set of embeddings that encapsulate the semantic and syntactic nuances of the language.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text Processing&lt;/strong&gt;: Text is input into the encoder, which then produces embeddings. These embeddings capture the textual context and are crucial for the model to understand and generate language-based responses.&lt;/li&gt;
&lt;/ul&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%2Fti4g03eculib7tfli4jn.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%2Fti4g03eculib7tfli4jn.png" alt=" " width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Integration and Output Generation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The final stage in the VLM involves integrating the outputs from both the image and text encoders. This integration occurs within a LLM, where both sets of embeddings interact through the Transformer's attention mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contextual Interaction&lt;/strong&gt;: The image and text token embeddings are combined and processed through the Transformer model. This interaction allows the model to contextualize the information from both modalities, enhancing its ability to generate accurate and relevant responses based on both text and visual inputs.&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%2F4ztd1s5c2yy8r3epgszl.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%2F4ztd1s5c2yy8r3epgszl.png" alt=" " width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This comprehensive approach enables VLMs to perform complex tasks that require an understanding of both visual elements and textual information, making them ideal for tasks like multimodal RAG where nuanced document understanding is critical.&lt;/p&gt;

&lt;p&gt;So, now that we learnt a bit about vision based language model, lets go back to ColPali and see how it precesses the data and generate the embeddings using the vision based model. &lt;/p&gt;

&lt;h2&gt;
  
  
  ColPali Embeddings Process
&lt;/h2&gt;

&lt;p&gt;Remember how we started by dividing a document into patches? &lt;strong&gt;ColPali&lt;/strong&gt; treats each page of a document as an image and divides it into patches, typically something like &lt;strong&gt;32×32&lt;/strong&gt;, resulting in &lt;strong&gt;1024 patches per page&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it like how your eyes scan a document, &lt;strong&gt;section by section&lt;/strong&gt;. These patches are processed individually to capture &lt;strong&gt;local visual details&lt;/strong&gt;, while also maintaining their &lt;strong&gt;spatial relationship&lt;/strong&gt; to the entire page.&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%2Fn1f2p0xgsm02k27ntk90.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%2Fn1f2p0xgsm02k27ntk90.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each of these patches is converted into a &lt;strong&gt;rich embedding&lt;/strong&gt; - a numerical representation that captures both visual and textual information. This is achieved through a vision encoder and a language model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;vision encoder&lt;/strong&gt; breaks down image patches into initial embeddings&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;transformer-based&lt;/strong&gt; LLM refines these embeddings to capture semantic information&lt;/li&gt;
&lt;/ol&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%2Fcabv9km1jb9uk8flu5zr.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%2Fcabv9km1jb9uk8flu5zr.png" alt=" " width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Query Time : Similarity Scoring
&lt;/h2&gt;

&lt;p&gt;When a user query comes in, ColPali calculates similarity scores between the query and document patches of each page through a scoring matrix. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Generating and Projecting Tokens&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1) Token Generation:&lt;/strong&gt; Initially, tokens and their embeddings are generated for the query. This involves transforming the text of the query into a format that the system can process and match against document embeddings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Projection:&lt;/strong&gt;  These tokens are then passed through the same transformer model used during the embedding process. This step involves projecting the tokens into the same embedding space as the document patches, ensuring that the subsequent comparisons are meaningful and accurate.&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%2Fquzghsvd4jcd0jnoqe4i.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%2Fquzghsvd4jcd0jnoqe4i.png" alt=" " width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: &lt;strong&gt;Computing the ColBERT Scoring Matrix&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;At this point, we have two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Query embeddings&lt;/li&gt;
&lt;li&gt;Embeddings of all pages (at patch level granularity)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next critical step involves computing the ColBERT scoring matrix. Here's how it works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Embedding Matchup:&lt;/strong&gt; The scoring matrix is essentially a grid where each row corresponds to a query token and each column to a document patch. The entries in the matrix represent the similarity scores, typically calculated as the dot product between the query token embeddings and the document patch embeddings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2) Score Maximization:&lt;/strong&gt; For each query token, the system identifies the maximum similarity score across all document patches. This step is crucial because it ensures that the most relevant patches are considered for generating the response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3) Summation for Final Score:&lt;/strong&gt; The maximum scores for each query token are then summed up to produce a final score for each document page. This cumulative score represents the overall relevance of the page to the query.&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%2Fozjoy631vb9oktsz2nn9.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%2Fozjoy631vb9oktsz2nn9.png" alt=" " width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: &lt;strong&gt;Selecting Top-K Pages&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Based on the scores computed:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1) Ranking and Retrieval:&lt;/strong&gt; The pages are ranked according to their scores, and the top-scoring pages are selected. This selection of &lt;code&gt;top-K&lt;/code&gt; pages is crucial as it filters out the pages most likely to contain the information sought by the query.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2)Response Generation:&lt;/strong&gt; These top pages are then fed, along with the query, into a multimodal language model like Amazon Nova. The model uses both the textual and the visual cues from these pages to generate detailed and contextually accurate responses.&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%2Fzakal51opjbk3hj8usib.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%2Fzakal51opjbk3hj8usib.png" alt=" " width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn more about ColPali, you can refer to the &lt;a href="https://github.com/illuin-tech/colpali" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and also I would recommend you to read the 9 part blog series on RAG on &lt;a href="https://www.dailydoseofds.com/" rel="noopener noreferrer"&gt;DailyDoseofDS&lt;/a&gt; by Avi Chawla and Akshay Pachaar. &lt;/p&gt;

&lt;p&gt;Ok, enough of theory. Let's see it in action :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Building an Agentic RAG System with CrewAI
&lt;/h2&gt;

&lt;p&gt;Having a powerful retrieval model is just &lt;strong&gt;one piece of the puzzle&lt;/strong&gt;. To create a truly intelligent system, we need to orchestrate the workflow, this is where CrewAI comes in. &lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;CrewAI&lt;/strong&gt;, we’ll define &lt;strong&gt;specialized AI agents&lt;/strong&gt; that work collaboratively to execute complex tasks. Each agent is responsible for a specific role, and together, they handle the &lt;strong&gt;retrieval&lt;/strong&gt;, &lt;strong&gt;reasoning&lt;/strong&gt;, and &lt;strong&gt;response generation,&lt;/strong&gt; all under the hood.&lt;/p&gt;

&lt;p&gt;Here's how our architecture will look:&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%2Fo7nn0vl9h4vp1v83dnjk.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%2Fo7nn0vl9h4vp1v83dnjk.png" alt=" " width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;To follow along with this tutorial, I recommend cloning &lt;a href="https://github.com/debnsuma/fcc-ai-engineering-aws/blob/main/06-agents-with-rag/02-multimodal-retrival-with-colpali-retreve-gen-agents-crewAI.ipynb/?trk=7dd6ab1d-561b-49c6-bae9-b5978e1e2073&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;this repo&lt;/a&gt; from GitHub and follow along:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;colpali-engine torch boto3 tqdm pymupdf numpy matplotlib einops seaborn &lt;span class="nt"&gt;-q&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;boto3&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.34.162 &lt;span class="nv"&gt;botocore&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;1.34.162 &lt;span class="nv"&gt;crewai&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.70.1 &lt;span class="nv"&gt;crewai_tools&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;0.12.1 &lt;span class="nv"&gt;PyPDF2&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;3.0.1 &lt;span class="nt"&gt;-q&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s import few of the libraries,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;shutil&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;boto3&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;huggingface_hub&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;login&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;colpali_engine.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ColPali&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ColPaliProcessor&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;pdf2image&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;convert_from_path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;qdrant_client.http&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;models&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tqdm&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tqdm&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;matplotlib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pyplot&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;plt&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;PIL&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Image&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crewai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LLM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Process&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;IPython.display&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Markdown&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Download the dataset
&lt;/h2&gt;

&lt;p&gt;First, let’s create a directory in your current working directory to store the dataset.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pdf_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pdf_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exist_ok&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this demo, we'll be using the &lt;strong&gt;Class X Science book from NCERT&lt;/strong&gt;, which is publicly available on &lt;a href="https://ncert.nic.in/textbook.php?jesc1=0-13" rel="noopener noreferrer"&gt;their official website&lt;/a&gt;. Once you download the PDF, save it within the folder &lt;code&gt;pdf_data&lt;/code&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Load the ColPali Multimodal Document Retrieval Model
&lt;/h2&gt;

&lt;p&gt;We will now load the ColPali model from &lt;a href="https://huggingface.co/vidore/colpali-v1.2" rel="noopener noreferrer"&gt;HuggingFace&lt;/a&gt;. In case you don’t have any account created in HF, this is the time to sign up and create a HUGGING_FACE_TOKEN. You’ll need this token to authenticate and access gated models.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Loading the token
&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;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HUGGING_FACE_TOKEN&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;YOUR_HF_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; 

&lt;span class="c1"&gt;# Login using token from environment variable
&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HUGGING_FACE_TOKEN&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;p&gt;If you're running this code on a machine with a GPU or MPS (for Mac), it's highly recommended to use it for more efficient processing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt; 

&lt;span class="c1"&gt;# Check if CUDA/MPS/CPU is available
&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cuda&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cuda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mps&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backends&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_available&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cpu&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="nf"&gt;print&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt; &lt;span class="o"&gt;=&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s load the &lt;strong&gt;ColPali&lt;/strong&gt; model and its processor from Hugging Face.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vidore/colpali-v1.3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;colpali_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ColPali&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;pretrained_model_name_or_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;torch_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bfloat16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                &lt;span class="n"&gt;cache_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./model_cache&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;colpali_processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ColPaliProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;pretrained_model_name_or_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;cache_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;./model_cache&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;h2&gt;
  
  
  Setting up the vector database
&lt;/h2&gt;

&lt;p&gt;Before we generate embeddings using the &lt;strong&gt;ColPali&lt;/strong&gt; model, we need a place to &lt;strong&gt;store and query&lt;/strong&gt; them. That’s where a &lt;strong&gt;vector database&lt;/strong&gt; is needed.&lt;/p&gt;

&lt;p&gt;For this tutorial, we’re using &lt;strong&gt;Qdrant&lt;/strong&gt;, an open-source, high-performance vector database designed specifically for handling high-dimensional vector data.&lt;/p&gt;

&lt;p&gt;One of the great things about Qdrant is that it’s easy to self-host using Docker, making local development and experimentation super convenient.&lt;/p&gt;

&lt;p&gt;Like other vector stores, Qdrant supports &lt;strong&gt;fast similarity search&lt;/strong&gt; across millions (or even billions) of vectors. But it also offers &lt;strong&gt;rich filtering capabilities&lt;/strong&gt;, which makes it a solid choice for powering RAG pipelines where precision and flexibility matter.&lt;/p&gt;

&lt;p&gt;Run it on the shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 6333:6333 &lt;span class="nt"&gt;-p&lt;/span&gt; 6334:6334 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/qdrant_storage:/qdrant/storage:z &lt;span class="se"&gt;\&lt;/span&gt;
    qdrant/qdrant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once Qdrant is up and running, you can access the &lt;a href="http://%20http//localhost:6333/dashboard#/welcome" rel="noopener noreferrer"&gt;Qdrant Dashboard locally&lt;/a&gt;&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%2F3etzffyra8mr3bj49gh9.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%2F3etzffyra8mr3bj49gh9.png" alt=" " width="726" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have the &lt;strong&gt;Qdrant vector database&lt;/strong&gt; running locally, let’s create a &lt;strong&gt;client object&lt;/strong&gt; and define a &lt;strong&gt;collection&lt;/strong&gt; called &lt;code&gt;class_XII_science_book&lt;/code&gt; to store our embeddings.&lt;/p&gt;

&lt;p&gt;We’ll use the official Qdrant Python client to interact with the database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;qdrant_client&lt;/span&gt;

&lt;span class="c1"&gt;# Step 1: Creating a qdrant client object 
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;qdrant_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QdrantClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6333&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Create a collection
&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;class_XII_science_book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;VECTOR_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_collection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;on_disk_payload&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;vectors_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;VectorParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;VECTOR_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Distance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COSINE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;on_disk&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;multivector_config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MultiVectorConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;comparator&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MultiVectorComparator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MAX_SIM&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can check the the newly created collection in the &lt;a href="http://localhost:6333/dashboard#/collections" rel="noopener noreferrer"&gt;dashboard&lt;/a&gt; as well,&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%2Fb93frkb3411j236eilh7.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%2Fb93frkb3411j236eilh7.png" alt=" " width="616" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Store embeddings in vector database
&lt;/h2&gt;

&lt;p&gt;Now that our &lt;strong&gt;Qdrant vector database&lt;/strong&gt; is set up and our collection is ready, it's time to &lt;strong&gt;generate embeddings&lt;/strong&gt; using the &lt;strong&gt;ColPali&lt;/strong&gt; model and &lt;strong&gt;store them&lt;/strong&gt; in the collection.&lt;/p&gt;

&lt;p&gt;Let’s walk through the steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TOKENIZERS_PARALLELISM&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; 

&lt;span class="c1"&gt;# Step 1: Convert PDFs into a dictionary of PIL images 
# which will be used to create embeddings
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;convert_pdfs_to_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;poppler_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/opt/homebrew/bin&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;Convert PDFs into a dictionary of PIL images.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;pdf_files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_folder&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;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.pdf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;all_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pdf_file&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_files&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;pdf_path&lt;/span&gt; &lt;span class="o"&gt;=&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;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_folder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pdf_file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;convert_from_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pdf_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;poppler_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;poppler_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;page_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;all_images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;page_num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RGB&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="n"&gt;all_images&lt;/span&gt;



&lt;span class="c1"&gt;# Step 2: Create embeddings for the images
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;tqdm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;desc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Indexing Progress&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pbar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Extract images
&lt;/span&gt;        &lt;span class="n"&gt;images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="c1"&gt;# Process and encode images
&lt;/span&gt;        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;batch_images&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colpali_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;image_embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;batch_images&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Prepare points for Qdrant
&lt;/span&gt;        &lt;span class="n"&gt;points&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_embeddings&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;PointStruct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Use the batch index as the ID
&lt;/span&gt;                    &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embedding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  &lt;span class="c1"&gt;# Convert to list
&lt;/span&gt;                    &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;doc_id&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;page_num&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_num&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;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;  
                &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Upload points to Qdrant
&lt;/span&gt;        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;upsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;points&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="nf"&gt;print&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;Error during upsert: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&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="k"&gt;continue&lt;/span&gt;

        &lt;span class="c1"&gt;# Update the progress bar
&lt;/span&gt;        &lt;span class="n"&gt;pbar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;# Step 3: Generate embeddings and store in Qdrant
&lt;/span&gt;&lt;span class="n"&gt;PDF_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pdf_dir&lt;/span&gt;  &lt;span class="c1"&gt;# Change this to your actual folder path
&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;convert_pdfs_to_images&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PDF_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Generating embeddings and storing in Qdrant...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Indexing complete!&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;p&gt;Once this is done, we can check the embeddings in the dashboard &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%2Fcx2z1f5n4yecgjvp3m9f.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%2Fcx2z1f5n4yecgjvp3m9f.png" alt=" " width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the embeddings stored in Qdrant, we can now &lt;strong&gt;send a query&lt;/strong&gt; and retrieve the &lt;strong&gt;most similar pages&lt;/strong&gt; using vector similarity.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Step 1: Our query
&lt;/span&gt;&lt;span class="n"&gt;query_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What are the effects of oxidation reactions in everyday life ?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Generate embeddings for the query
&lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;text_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colpali_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_queries&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;query_text&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="n"&gt;text_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;text_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;token_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_embedding&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Step 3: Query the vector database
&lt;/span&gt;&lt;span class="n"&gt;query_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                   &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                   &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                   &lt;span class="n"&gt;search_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                   &lt;span class="n"&gt;quantization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QuantizationSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                   &lt;span class="n"&gt;ignore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                   &lt;span class="n"&gt;rescore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                   &lt;span class="n"&gt;oversampling&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;
                                   &lt;span class="p"&gt;)&lt;/span&gt;
                               &lt;span class="p"&gt;)&lt;/span&gt;
                           &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&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;Time taken = &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return the &lt;strong&gt;Top-K most similar pages&lt;/strong&gt; &lt;code&gt;(limit=5)&lt;/code&gt; based on the vector similarity between your query and the stored page embeddings.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# output of print(query_result.points)
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nc"&gt;ScoredPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;21.797455&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="nc"&gt;ScoredPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;19.110117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="nc"&gt;ScoredPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;19.051605&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="nc"&gt;ScoredPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;18.964575&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
 &lt;span class="nc"&gt;ScoredPoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;score&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;16.669119&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&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;doc_id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;source&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;pdf archive&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order_value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Building an Agentic RAG System with CrewAI
&lt;/h2&gt;

&lt;p&gt;Now, let’s level up. Retrieval alone isn’t enough, we need orchestration. To build a system that can reason and respond intelligently, we need to &lt;strong&gt;orchestrate the entire workflow, from query to retrieval to generation&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;That’s where &lt;a href="https://docs.crewai.com/introduction" rel="noopener noreferrer"&gt;CrewAI&lt;/a&gt; steps in.&lt;/p&gt;

&lt;p&gt;In this final section, we’ll build an &lt;strong&gt;agentic RAG pipeline&lt;/strong&gt; using CrewAI, where each part of the process will be handled by a dedicated agent, and they will work together to generate accurate, context-rich answers automatically.&lt;/p&gt;

&lt;p&gt;We’ll define two agents: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The Knowledge Retriever Agent :&lt;/strong&gt; Uses ColPali + Qdrant to fetch the most relevant pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Multimodal Knowledge Expert Agent :&lt;/strong&gt; Uses Amazon Nova to analyze the images and generate an answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s start by creating these agents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Define the Knowledge Retriever Agent 
&lt;/span&gt;&lt;span class="n"&gt;retrieval_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Knowledge Retriever&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retrieve the most relevant textbook pages from the knowledge base based on the student’s question.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;backstory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An intelligent academic assistant trained with NCERT Class X Science. It specializes in pinpointing the most relevant content based on the student’s question and the subject it pertains to.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;retrieve_from_qdrant&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;allow_delegation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the Multimodal Knowledge Expert Agent
&lt;/span&gt;&lt;span class="n"&gt;answering_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Multimodal Knowledge Expert&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;goal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accurately interpret the provided images and extract relevant information to answer the question: {query_text}.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;backstory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;An advanced AI specialized in multimodal reasoning, capable of analyzing both text and images to provide the most precise and insightful answers.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;multimodal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;allow_delegation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;llm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;llm&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if you take a closer look at the &lt;code&gt;retrieval_agent&lt;/code&gt; definition, you’ll notice we’ve included a tool called &lt;code&gt;retrieve_from_qdrant&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;We haven’t defined it yet, but this tool is the most important component in this agent definition. This is the tool which will enable the agent to &lt;strong&gt;perform semantic search under the hood&lt;/strong&gt;. Using this tool, the agent can interact with the Qdrant vector database, run a vector similarity search, and retrieve the most relevant document pages needed to answer the user’s query.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and define that next.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;crewai_tools&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize CrewAI LLM (Amazon Nova Pro) 
&lt;/span&gt;&lt;span class="n"&gt;model_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;us.amazon.nova-pro-v1:0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  
&lt;span class="n"&gt;llm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LLM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a Retrieval Tool 
&lt;/span&gt;&lt;span class="nd"&gt;@tool&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve_from_qdrant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&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="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Retrieve the most relevant documents from Qdrant vector database
    based on the given text query.

    Args:
        query (str): The user query to search in the knowledge base.

    Returns:
        list: List of paths to the matched images.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colpali_processor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;colpali_model&lt;/span&gt;

    &lt;span class="nf"&gt;print&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;Retrieving documents for query: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;query&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="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;no_grad&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="n"&gt;text_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;colpali_processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;process_queries&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
        &lt;span class="n"&gt;text_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;colpali_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;text_embedding&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;token_query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text_embedding&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;cpu&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;tolist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Perform search in Qdrant
&lt;/span&gt;    &lt;span class="n"&gt;query_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query_points&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;collection_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COLLECTION_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token_query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;search_params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;SearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;quantization&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;QuantizationSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;ignore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;rescore&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;oversampling&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&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;Query Time: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;start_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;matched_images_path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# Define a folder to save matched images
&lt;/span&gt;    &lt;span class="n"&gt;MATCHED_IMAGES_DIR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matched_images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Delete all files and the directory itself if it exists
&lt;/span&gt;    &lt;span class="k"&gt;if&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;MATCHED_IMAGES_DIR&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;shutil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rmtree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MATCHED_IMAGES_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;makedirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MATCHED_IMAGES_DIR&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;query_result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;points&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;page_num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;dataset&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;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;doc_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;doc_id&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;page_num&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;page_num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;image_filename&lt;/span&gt; &lt;span class="o"&gt;=&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;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;matched_images&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;match_doc_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;doc_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_page_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;page_num&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;image&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;matched_images_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image_filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="nf"&gt;print&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;Saved: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;image_filename&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="k"&gt;break&lt;/span&gt;  

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;All matched images are saved in the &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;matched_images&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; folder.&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="n"&gt;matched_images_path&lt;/span&gt;



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

&lt;/div&gt;



&lt;p&gt;Now, we can define the tasks for each of these agents and create the Crew.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="c1"&gt;# Define the task for the Knowledge Retriever Agent
&lt;/span&gt;&lt;span class="n"&gt;retrieval_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Retrieve the most relevant images from the knowledge base based on the given query.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;retrieval_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;expected_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A list of image file paths related to the query.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define the task for the the Multimodal Knowledge Expert Agent
&lt;/span&gt;&lt;span class="n"&gt;answering_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Using the retrieved images at {{matched_images_path}}, generate a precise answer to the query: {{query_text}}.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;answering_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Assign answering agent
&lt;/span&gt;    &lt;span class="n"&gt;expected_output&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;A clear and well-structured explanation based on the extracted information from the images. No need to include reference to the images in the answer.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Assemble the Crew 
&lt;/span&gt;&lt;span class="n"&gt;crew&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Crew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;agents&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;retrieval_agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answering_agent&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;retrieval_task&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;answering_task&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  
    &lt;span class="n"&gt;process&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sequential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Query Time
&lt;/h2&gt;

&lt;p&gt;Let's see how this system works with a real example. Imagine a student asks about &lt;em&gt;“the proper way to heat a boiling tube containing ferrous sulphate crystals and how to safely smell the odor”,&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#  Run the Query 
&lt;/span&gt;&lt;span class="n"&gt;query_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What is the correct way of heating the boiling tube containing crystals of ferrous sulphate and of smelling the odour&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;kickoff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&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;query_text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;query_text&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The final output ?  detailed explanation pulled from textbook pages that includes both textual and visual cues. The system identifies diagrams, interprets scientific procedures, and provides safe lab instructions, just like a teacher would :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This approach represents an exciting step toward more human-like document understanding. By combining vision-language models with specialized agents, we can create systems that process information more holistically - considering layout, visual elements, and text as an integrated whole.&lt;/p&gt;

&lt;p&gt;As vision language models continue to improve, and frameworks like CrewAI become more sophisticated, we can expect even more powerful multimodal RAG systems that further close the gap between how humans and machines process information.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Next
&lt;/h2&gt;

&lt;p&gt;If you’re exploring multimodal retrieval and generation, I’d highly recommend checking out my free course on &lt;strong&gt;Multimodal RAG and Embeddings&lt;/strong&gt; in collaboration with Analytics Vidhya. It covers foundational concepts like embeddings, Byte-Pair Encoding, and vision-language reasoning using Amazon Nova and Bedrock. &lt;/p&gt;

&lt;p&gt;📖 Course Topics:&lt;/p&gt;

&lt;p&gt;✅ Embeddings in NLP &amp;amp; LLMs (Amazon Tian Text Embeddings)&lt;br&gt;
✅ Byte-Pair Encoding (BPE)&lt;br&gt;
✅ Multimodal LLMs &amp;amp; Contrastive Learning (CLIP, BLIP-2, Amazon Nova)&lt;br&gt;
✅ Multimodal RAG &amp;amp; Knowledge Bases with Amazon Bedrock&lt;br&gt;
✅ End-to-end AI application development with Agents and Knowledge Base&lt;/p&gt;

&lt;p&gt;Get access here: &lt;a href="https://courses.analyticsvidhya.com/courses/mastering-multimodal-rag-and-embeddings-with-amazon-nova-and-bedrock/?trk=7dd6ab1d-561b-49c6-bae9-b5978e1e2073&amp;amp;sc_channel=el" rel="noopener noreferrer"&gt;Mastering Multimodal RAG Course&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you working on any &lt;strong&gt;multimodal use cases&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;I’d love to hear about them, connect with me on &lt;a href="https://www.linkedin.com/in/suman-d/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rag</category>
      <category>llm</category>
      <category>bedrock</category>
      <category>colpali</category>
    </item>
    <item>
      <title>Machine Learning in SQL Style (Part-2)</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Thu, 04 Mar 2021 14:50:38 +0000</pubDate>
      <link>https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl</link>
      <guid>https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl</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%2Fe0m60hx4s457zot08f9b.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%2Fe0m60hx4s457zot08f9b.png" alt="imgh1" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuing our learning from where we left in the &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc"&gt;Part-1&lt;/a&gt; of this tutorial series, where we discussed about Amazon Redshift briefly and dive deep into Amazon Redshift ML. We also learnt about, how a database engineer/administrator could make use of Redshift ML to &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;train&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; a machine learning model using familiar SQL commands. &lt;/p&gt;

&lt;p&gt;Now, we are going to see some of the advanced functionalities of Amazon Redshift ML which a Data Analyst or an expert Data Scientist can make use of, which offers more flexibility in terms of defining specific information, like which &lt;code&gt;algorithm&lt;/code&gt; to use (such as XGBoost), specifying &lt;code&gt;hyperparameter&lt;/code&gt;, &lt;code&gt;preprocessor&lt;/code&gt; and so on. &lt;/p&gt;

&lt;h1&gt;
  
  
  Exercise 2 (Data Analyst's perspective)
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Dataset
&lt;/h3&gt;

&lt;p&gt;In this problem, we are going to use the &lt;a href="https://archive.ics.uci.edu/ml/datasets/Steel+Plates+Faults" rel="noopener noreferrer"&gt;Steel Plates Faults Data Set&lt;/a&gt; from &lt;a href="https://archive.ics.uci.edu/ml/index.php" rel="noopener noreferrer"&gt;UCI Machine Learning Repository&lt;/a&gt;. You can download the dataset from this &lt;a href="https://github.com/debnsuma/redshiftml-demo/tree/master/dataset" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This dataset is related to the quality of steel plates, wherein there are 27 &lt;code&gt;independent variables&lt;/code&gt; (input features) which comprises of various attributes of a steel plate and one &lt;code&gt;dependent variable&lt;/code&gt; (class label) which can be of 1 of 7 types. So, the problem in hand is a multi-class classification problem, where we need to predict the fault in the steel plate, given 7 different types of the faults that it can have. &lt;/p&gt;

&lt;p&gt;So, the &lt;code&gt;objective&lt;/code&gt; is to &lt;em&gt;predict&lt;/em&gt; what is the &lt;code&gt;fault&lt;/code&gt; the steel plate has (&lt;em&gt;Pastry, Z_Scratch, K_Scatch, Stains, Dirtiness, Bumps or Other_Faults&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;As we have seen in &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc"&gt;Part-1&lt;/a&gt;, since our dataset is located in Amazon S3, first we need to load the data in table. We can open DataGrip(or whatever SQL Connector you are using) and create the &lt;code&gt;schema&lt;/code&gt; and the &lt;code&gt;table&lt;/code&gt;. Once that is done, we can use &lt;code&gt;COPY&lt;/code&gt; command to load the training data from Amazon S3 (&lt;em&gt;steel_fault_train.csv&lt;/em&gt;) to the &lt;code&gt;Redshift&lt;/code&gt; cluster, in the table, &lt;code&gt;steel_plates_fault&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As always, we need to make sure that colum names of the table matches with the feature sets in the &lt;code&gt;CSV&lt;/code&gt; training dataset file. &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%2Ffzc75juse71cpqm7400h.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%2Ffzc75juse71cpqm7400h.png" alt="img1" width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly we can load the dataset for the testing(&lt;em&gt;steel_fault_test.csv&lt;/em&gt;) in a separate table, &lt;code&gt;steel_plates_fault_inference&lt;/code&gt;&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%2F1y3hlwt2iusemsvmosyj.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%2F1y3hlwt2iusemsvmosyj.png" alt="img2" width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Training (Model Creation)
&lt;/h3&gt;

&lt;p&gt;Now, being a data analyst, you may like to explicitly mention few of the parameters, like &lt;code&gt;PROBLEM_TYPE&lt;/code&gt; and &lt;code&gt;OBJECTIVE&lt;/code&gt; function. When you provide this information while creating the model, Amazon SageMaker Autopilot chooses the &lt;code&gt;PROBLEM_TYPE&lt;/code&gt; and &lt;code&gt;OBJECTIVE&lt;/code&gt; specified by you, instead of tying everything.  &lt;/p&gt;

&lt;p&gt;Like for this problem, we are going to provide the &lt;code&gt;PROBLEM_TYPE&lt;/code&gt; as &lt;code&gt;multiclass_classification&lt;/code&gt; and &lt;code&gt;OBJECTIVE&lt;/code&gt; as &lt;code&gt;accuracy&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Other &lt;code&gt;PROBLEM_TYPE&lt;/code&gt; we can specify are : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REGRESSION &lt;/li&gt;
&lt;li&gt;BINARY_CLASSIFICATION &lt;/li&gt;
&lt;li&gt;MULTICLASS_CLASSIFICATION&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similarly, &lt;code&gt;OBJECTIVE&lt;/code&gt; function could be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MSE &lt;/li&gt;
&lt;li&gt;Accuracy &lt;/li&gt;
&lt;li&gt;F1&lt;/li&gt;
&lt;li&gt;F1Macro&lt;/li&gt;
&lt;li&gt;AUC &lt;/li&gt;
&lt;/ul&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%2F44bdrvro44ujjvit294d.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%2F44bdrvro44ujjvit294d.png" alt="img3" width="800" height="844"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we have learnt in the &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc"&gt;PART-1&lt;/a&gt; of the tutorial, the &lt;code&gt;CREATE MODEL&lt;/code&gt; command operates in an &lt;code&gt;asynchronous&lt;/code&gt; mode and it returns the response upon the export of training data to Amazon S3. As the remaining steps of model training and compilation can take a longer time, it continues to run in the background.&lt;/p&gt;

&lt;p&gt;But we can always check the status of the training using the &lt;code&gt;STV_ML_MODEL_INFO&lt;/code&gt; function, and wait till the &lt;code&gt;model_state&lt;/code&gt; becomes &lt;code&gt;Model is Ready&lt;/code&gt;. &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%2Ffqaj5ueus84qv4u4bj9f.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%2Ffqaj5ueus84qv4u4bj9f.png" alt="img4" width="800" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's look at the details about the model, and see if it has used the same &lt;code&gt;PROBLEM_TYPE&lt;/code&gt; and &lt;code&gt;OBJECTIVE&lt;/code&gt; function which we mentioned while executed the &lt;code&gt;CREATE MODEL&lt;/code&gt; command&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%2Ff0oihm67ms8dz06r5yx3.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%2Ff0oihm67ms8dz06r5yx3.png" alt="img5" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accuracy of the Model and Prediction/Inference
&lt;/h3&gt;

&lt;p&gt;Lastly, let's try to see what's the accuracy of our model using the test data which we have in the &lt;code&gt;steel_plates_fault_inference&lt;/code&gt; table.  &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%2F0y5zpferntbzyu6nlf0t.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%2F0y5zpferntbzyu6nlf0t.png" alt="img6" width="800" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see the accuracy is around &lt;code&gt;77%&lt;/code&gt;, which is not all that great, but this is because we used a very small dataset to train the model, &lt;code&gt;func_model_steel_fault&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;And finally, let's try to do some prediction using this same model function &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%2Fy7r65kirxmyzn20a0hny.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%2Fy7r65kirxmyzn20a0hny.png" alt="img7" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lastly, let's take another example and this time from a Data Scientist's perspective, wherein we will make use of some more advanced options while executing the &lt;code&gt;CREATE MODEL&lt;/code&gt; command.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exercise 3 (Data Scientist's perspective)
&lt;/h1&gt;

&lt;p&gt;So the last two problems we worked on, were &lt;code&gt;classification&lt;/code&gt; problem (binary and multi-class), and this time we will work on a &lt;code&gt;regression&lt;/code&gt; problem and shall use some more advanced parameters while training the model (like mentioning the training algorithm, hyperparameter, etc.). &lt;/p&gt;

&lt;h3&gt;
  
  
  Dataset
&lt;/h3&gt;

&lt;p&gt;In this problem, we are going to use the &lt;a href="https://archive.ics.uci.edu/ml/datasets/Abalone" rel="noopener noreferrer"&gt;Abalone Data Set&lt;/a&gt; from &lt;a href="https://archive.ics.uci.edu/ml/index.php" rel="noopener noreferrer"&gt;UCI Machine Learning Repository&lt;/a&gt;. You can download the dataset from this &lt;a href="https://github.com/debnsuma/redshiftml-demo/tree/master/dataset" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this problem we need to predict the age of a abalone from its physical measurements. The age of abalone is determined by cutting the shell through the cone, staining it, and counting the number of rings through a microscope -- a boring and time-consuming task. &lt;/p&gt;

&lt;p&gt;The dataset is having total 7 &lt;code&gt;input features&lt;/code&gt; and 1 &lt;code&gt;target&lt;/code&gt;, which is nothing but the &lt;code&gt;age&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;So, first let's create the &lt;code&gt;schema&lt;/code&gt; and the &lt;code&gt;table&lt;/code&gt;. Once that is done, we can use &lt;code&gt;COPY&lt;/code&gt; command to load the training data from Amazon S3 (&lt;em&gt;xgboost_abalone_train.csv&lt;/em&gt;) to the &lt;code&gt;Redshift&lt;/code&gt; cluster, in the table, &lt;code&gt;abalone_xgb_train&lt;/code&gt;.&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%2Fjvgh321lf6kqq12xn6sq.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%2Fjvgh321lf6kqq12xn6sq.png" alt="img8" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly we can load the dataset for the testing(&lt;em&gt;xgboost_abalone_test.csv&lt;/em&gt;) from Amazon S3, in a separate table, &lt;code&gt;abalone_xgb_test&lt;/code&gt;&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%2Fo9pozfykyrbpkcdp1zhn.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%2Fo9pozfykyrbpkcdp1zhn.png" alt="img9" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Training (Model Creation)
&lt;/h3&gt;

&lt;p&gt;As a data scientist, you may like to have more control over training the model, e.g you may decide to provide more granular options, like &lt;code&gt;MODEL_TYPE&lt;/code&gt; , &lt;code&gt;OBJECTIVE&lt;/code&gt;, &lt;code&gt;PREPROCESSORS&lt;/code&gt; and &lt;code&gt;HYPER PARAMETERS&lt;/code&gt; while running the &lt;code&gt;CREATE MODEL&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;As an advanced user, you may already know the model type that you want and hyperparameter to use when training these models. You can use &lt;code&gt;CREATE MODEL&lt;/code&gt; command with &lt;code&gt;AUTO OFF&lt;/code&gt; to turn off the &lt;code&gt;CREATE MODEL&lt;/code&gt; automatic discovery of preprocessors and hyperparameters. &lt;/p&gt;

&lt;p&gt;For this problem we are going to specify &lt;code&gt;MODEL_TYPE&lt;/code&gt; as &lt;code&gt;xgboost&lt;/code&gt;(&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/xgboost.html" rel="noopener noreferrer"&gt;Xtreme Gradient Boosted tree&lt;/a&gt;) which we can use for both regression and classification based problems. XGBoost is currently the &lt;em&gt;only&lt;/em&gt; &lt;code&gt;MODEL_TYPE&lt;/code&gt; supported when AUTO is set to OFF. We are also going to use the &lt;code&gt;OBJECTIVE&lt;/code&gt; function as &lt;code&gt;reg:squarederror&lt;/code&gt;. You can specify hyperparameters as well. For more details, you may like to check the &lt;a href="https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_MODEL.html" rel="noopener noreferrer"&gt;Amazon Redshift ML Developer Guide&lt;/a&gt;(&lt;em&gt;CREATE MODEL section&lt;/em&gt;)&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%2Flla3ep6bp0xxm1j88w4a.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%2Flla3ep6bp0xxm1j88w4a.png" alt="img10" width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's look at the details about the model, as we did before:&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%2Fht0jluur0097289f5xv5.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%2Fht0jluur0097289f5xv5.png" alt="img11" width="800" height="491"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accuracy of the Model and Prediction/Inference
&lt;/h3&gt;

&lt;p&gt;Now, let's try to see what's the accuracy of our model, using the test data which we have in the &lt;code&gt;abalone_xgb_test&lt;/code&gt; table.  &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%2Fc11hq6vpd5lhcy61odja.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%2Fc11hq6vpd5lhcy61odja.png" alt="img12" width="755" height="483"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally let's try to do some prediction using this same model function, &lt;code&gt;func_model_abalone_xgboost_regression&lt;/code&gt;&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%2F6fknr2d1r915z6cbxqgq.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%2F6fknr2d1r915z6cbxqgq.png" alt="img13" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What next...
&lt;/h1&gt;

&lt;p&gt;So, in this tutorial we learnt about Amazon Redshift ML from an advanced users perspective (like Data Analyst or Data Scientist), and learnt how we can &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;train&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; a ML model using familiar SQL query. You can even go further and explore the training jobs which it internally initiates in the &lt;code&gt;Amazon SageMaker&lt;/code&gt; console, if you are interested. Feel free to give it a try and share your feedback. &lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt; : &lt;a href="https://github.com/debnsuma/redshiftml-demo.git" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog&lt;/strong&gt; : &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc"&gt;Amazon Redshift ML - Machine Learning in SQL Style (Part-1)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/redshift/features/redshift-ml/" rel="noopener noreferrer"&gt;Using machine learning in Amazon Redshift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Book&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.amazon.com/Learn-Amazon-SageMaker-developers-scientists-ebook/dp/B08FMWJXGN" rel="noopener noreferrer"&gt;Learn SageMaker&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Videos&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8zHh2DoQZBs" rel="noopener noreferrer"&gt;AWS on Air 2020: AWS What’s Next ft. Amazon Redshift Machine Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3BN1w8JUtD4" rel="noopener noreferrer"&gt;AWS re:Invent 2020: Introducing Amazon Redshift Machine Learning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>datascience</category>
      <category>database</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Machine Learning in SQL Style (Part-1)</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Thu, 04 Mar 2021 14:49:18 +0000</pubDate>
      <link>https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc</link>
      <guid>https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-1-22nc</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%2Ftcbf6jc6dafw3e47935c.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%2Ftcbf6jc6dafw3e47935c.png" alt="imgh1" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Machine learning(ML) is everywhere, you look around, you will see some or the other application is either built using ML or powered by ML. And with the advent of technology, specially cloud, every passing day ML is getting more and more reachable to developers, irrespective of their background. We at Amazon Web Services(AWS) are committed to put machine learning in the hands of every developer, data scientist and expert practitioner. Now, what if you can &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;train&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; a machine learning model using simple SQL commands? &lt;/p&gt;

&lt;p&gt;During &lt;a href="https://reinvent.awsevents.com/" rel="noopener noreferrer"&gt;re:Invent 2020&lt;/a&gt; we announced &lt;code&gt;Amazon Redshift ML&lt;/code&gt; which makes it easy for SQL users to &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;train&lt;/code&gt;, and &lt;code&gt;deploy&lt;/code&gt; ML models using familiar SQL commands. &lt;a href="https://aws.amazon.com/redshift/features/redshift-ml/" rel="noopener noreferrer"&gt;Amazon Redshift ML&lt;/a&gt; allows you to use your data in &lt;a href="https://aws.amazon.com/redshift" rel="noopener noreferrer"&gt;Amazon Redshift&lt;/a&gt; with &lt;a href="https://aws.amazon.com/sagemaker/" rel="noopener noreferrer"&gt;Amazon SageMaker&lt;/a&gt;(&lt;em&gt;a fully managed ML service&lt;/em&gt;), without requiring you to become experts in ML.&lt;/p&gt;

&lt;p&gt;Now, before we dive deep into what it is, how it works, etc. here are the things we will try to cover in this first part of the tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Amazon Redshift &lt;/li&gt;
&lt;li&gt;Introduction to Redshift ML &lt;/li&gt;
&lt;li&gt;How to get started and the prerequisites
&lt;/li&gt;
&lt;li&gt;I am a Database Administrator - What's in for me ?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in the &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl"&gt;Part-2&lt;/a&gt;, we will take that learning beyond and cover the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I am a Data Analyst - What's about me ? &lt;/li&gt;
&lt;li&gt;I am a Data Scientist - How can I make use of this ? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Overall, we will try to solve different problems which will help us to understand Amazon Redshift ML from a perspective of a database administrator, data analyst and an advanced machine learning expert. &lt;/p&gt;

&lt;p&gt;Before we get started and set the stage by reviewing what is Amazon Redshift?&lt;/p&gt;

&lt;h1&gt;
  
  
  Amazon Redshift
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;Amazon Redshift&lt;/code&gt; is a fully managed, petabyte-scale data warehousing service on the AWS. Its low-cost and highly scalable service, which allows you to get started on your data warehouse use-cases at a minimal cost and scale as the demand for your data grows. It uses a variety of innovations to obtain very high query performance on datasets ranging in size from a hundred gigabytes to a petabyte or more. It uses massively parallel processing(MPP), columnar storage and data compression encoding schemes to reduce the amount of I/O needed to perform queries, which allows it in distributing the SQL operations to take advantage of all available resources underneath. &lt;/p&gt;

&lt;p&gt;Let's quickly go over few core components of an Amazon Redshift Cluster: &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%2F2paxdnsuf7nxu5ferc1p.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%2F2paxdnsuf7nxu5ferc1p.png" alt="img1" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Client Application&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amazon Redshift integrates with various data loading and &lt;code&gt;ETL&lt;/code&gt; (&lt;em&gt;extract, transform, and load&lt;/em&gt;) tools and business intelligence (BI) reporting, data mining, and analytics tools. As Amazon Redshift is based on industry-standard &lt;em&gt;PostgreSQL&lt;/em&gt;, most of commonly used SQL client application should work, we are going to use &lt;a href="https://www.jetbrains.com/datagrip/" rel="noopener noreferrer"&gt;Jetbrains DataGrip&lt;/a&gt; to connect to our Redshift cluster(&lt;em&gt;via JDBC connection&lt;/em&gt;) later while we jump into the hands-on section. Having said that, you may like to use any other SQL Client tool like &lt;em&gt;SQL Workbench/J, psql tool, etc.&lt;/em&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Cluster&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The core infrastructure component of an Amazon Redshift data warehouse is a &lt;code&gt;cluster&lt;/code&gt;. A cluster is composed of one or more compute nodes. A cluster comprises of nodes, as shown in the above image, Redshift has two major node types: &lt;code&gt;leader node&lt;/code&gt; and &lt;code&gt;compute node&lt;/code&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Leader Node&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If we create a cluster with two or more no. of compute nodes, then an  additional &lt;code&gt;leader node&lt;/code&gt; coordinates the &lt;code&gt;compute nodes&lt;/code&gt; and handles external communication. We don't have to define a leader node, it will be automatically provisioned with every Redshift cluster. Once the cluster is created, the client application interacts directly only with the leader node. In other words, the &lt;code&gt;leader node&lt;/code&gt; behaves as the gateway(the SQL endpoint) of your cluster for all the clients. Few of the major tasks of the leader node is to store the metadata, coordinate with all the &lt;code&gt;compute nodes&lt;/code&gt; for parallel SQL processing and and to generate most optimized and efficient query plan.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Compute Nodes&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;compute nodes&lt;/code&gt; is the main workhorse for the Redshift cluster, and it sits behind the &lt;code&gt;leader node&lt;/code&gt;. The leader node compiles code for individual elements of the execution plan and assigns the code to individual compute node(s). After that, the compute node(s) execute the respective compiled code and send intermediate results back to the leader node for final aggregation. Each compute node has its own dedicated CPU, memory, and attached storage, which are determined by the &lt;a href="https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html" rel="noopener noreferrer"&gt;node type&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;node type&lt;/code&gt; determines the CPU, RAM, storage capacity, and storage drive type for each node. Amazon Redshift offers different node types to accommodate different types of workloads, so you can select which suits you the best, but its is recommended to use &lt;code&gt;ra3&lt;/code&gt;. The new &lt;code&gt;ra3&lt;/code&gt; nodes let you determine how much compute capacity you need to support your workload and then scale the amount of storage based on your needs.&lt;/p&gt;

&lt;p&gt;Ok, now that we understood a bit about the Redshift Cluster let's go back to the main topic, Redshift ML :)&lt;br&gt;
And don't worry if things are still dry for you, as soon as we jump into the demo and create a cluster from scratch, things will fall in place. &lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to Redshift ML
&lt;/h1&gt;

&lt;p&gt;We have been integrating ML functionality with many other services for long time, for example in re:Invent 2019, we announced &lt;a href="https://aws.amazon.com/rds/aurora/machine-learning/" rel="noopener noreferrer"&gt;Amazon Aurora Machine Learning&lt;/a&gt;, which enables you to add ML-based predictions to your applications via the familiar SQL programming language. Integration with ML is very important in today's world we live in. It helps any developer to build, train, and deploy your ML models efficiently and at scale.&lt;/p&gt;

&lt;p&gt;Following the ritual, during &lt;a href="https://reinvent.awsevents.com/" rel="noopener noreferrer"&gt;re:Invent 2020&lt;/a&gt;, we announced this new capability called Redshift ML, which enables any SQL user to &lt;code&gt;train&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; ML models using familiar SQL commands, without knowing much about machine learning. Having said that, if you are an intermediate machine learning practitioner or an expert Data Scientist, you still get the flexibility to define specific algorithms such as XGBoost and specify hyperparameter and preprocessor. &lt;/p&gt;

&lt;p&gt;The way it works is pretty simple, you provide the data that you want to train the model and metadata associated with data inputs to Amazon Redshift and then Amazon Redshift ML creates the model that capture patterns in the input data. And once the model is trained, you can then use the models to generate predictions for new input data without incurring additional costs.&lt;/p&gt;

&lt;p&gt;As of now, Amazon Redshift supports &lt;code&gt;supervised learning&lt;/code&gt;, that includes the following problem types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;regression&lt;/code&gt;: problem of predicting continuous values, such as the total spending of customers&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;binary classification&lt;/code&gt;: problem of predicting one of two outcomes, such as predicting whether a customer churns or not&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;multi-class classification&lt;/code&gt;: problem of predicting one of many outcomes, such as predicting the item a customer might be interested&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Supervised learning&lt;/strong&gt;&lt;/em&gt; is the machine learning task of &lt;em&gt;learning a function&lt;/em&gt; that maps an &lt;em&gt;input&lt;/em&gt; to an &lt;em&gt;output&lt;/em&gt; based on example &lt;em&gt;input-output&lt;/em&gt; pairs. It infers a function from labeled training data consisting of a set of training examples. In supervised learning, each example is a pair consisting of an input object (typically a vector) and a desired output value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The inputs used for the ML model are often referred to as &lt;code&gt;features&lt;/code&gt; or in ML terms, called &lt;code&gt;independent variables&lt;/code&gt;, and the outcomes or results are called &lt;code&gt;labels&lt;/code&gt; or &lt;code&gt;dependent variables&lt;/code&gt;. Your training dataset is a table or a query whose attributes or columns comprise features, and targets are extracted from your data warehouse. The following diagram illustrates this architecture.&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%2Fd344hueykvolea2bdpak.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%2Fd344hueykvolea2bdpak.png" alt="img2" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we understand that data analysts and database developers are very much familiar with SQL, as they use that day-in day-out. But to build, train and deploy any ML model in Amazon SageMaker, one need to learn some programming language(like Python) and study different types of machine learning algorithms and build an understanding of which algorithm to use for a particular problem. Or else you may rely on some ML expert to do your job on your behalf. &lt;/p&gt;

&lt;p&gt;Not just that, even if someone helped you to build, train and deployed your ML model, when you actually need to use the model to make some prediction on your new data, you need to repeatedly move the data back and forth between Amazon Redshift and Amazon Sagemaker through a series of manual and complicated steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export training data to Amazon Simple Storage Service (Amazon S3).&lt;/li&gt;
&lt;li&gt;Train the model in Amazon SageMaker.&lt;/li&gt;
&lt;li&gt;Export prediction input data to Amazon S3.&lt;/li&gt;
&lt;li&gt;Use prediction in Amazon SageMaker.&lt;/li&gt;
&lt;li&gt;Import predicted columns back into the database. &lt;/li&gt;
&lt;/ol&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%2Fmbq2y3ew4gfb9i45aehi.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%2Fmbq2y3ew4gfb9i45aehi.png" alt="img3" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All this is daunting, isn't it? &lt;/p&gt;

&lt;p&gt;But now, with Amazon Redshift ML, we don't have to do any of these, you can train model with one single &lt;code&gt;SQL CREATE MODEL&lt;/code&gt; command. So, you don't have to expertise in machine learning, tools, languages, algorithms, and APIs. &lt;/p&gt;

&lt;p&gt;Once you run the SQL command to create the model, Amazon Redshift ML securely exports the specified data from Amazon Redshift to Amazon S3 and calls SageMaker Autopilot to automatically prepare the data, select the appropriate pre-built algorithm, and apply the algorithm for model training. Amazon Redshift ML handles all the interactions between Amazon Redshift, Amazon S3, and SageMaker, abstracting the steps involved in training and compilation. &lt;/p&gt;

&lt;p&gt;And once the &lt;code&gt;model&lt;/code&gt; is trained, Amazon Redshift ML makes &lt;code&gt;model&lt;/code&gt; available as a SQL function in your Amazon Redshift data warehouse. &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%2Fsuvbsno2gr0wyjbko6c1.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%2Fsuvbsno2gr0wyjbko6c1.png" alt="img4" width="774" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, let's see all in action now...&lt;/p&gt;

&lt;h1&gt;
  
  
  Create Redshift Cluster
&lt;/h1&gt;

&lt;p&gt;Let's create a Redshift Cluster now, first we need to login to our AWS Console and search for Redshift and click on &lt;code&gt;Create cluster&lt;/code&gt;. &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%2Ffmvu3n7jlt5wzg7qyfa7.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%2Ffmvu3n7jlt5wzg7qyfa7.png" alt="img5" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, in the &lt;strong&gt;Cluster configuration&lt;/strong&gt; section, we need to provide some cluster identifier, let's say &lt;code&gt;redshift-cluster-1&lt;/code&gt; and select the appropriate &lt;code&gt;node type&lt;/code&gt; and number of nodes you would like to have in the cluster. As mentioned before, we recommend to choose &lt;code&gt;RA3&lt;/code&gt; node types, like &lt;em&gt;ra3.xplus, ra3.4xlarge&lt;/em&gt; and &lt;em&gt;ra3.16xlarge&lt;/em&gt; which offers the best in class performance with scalable managed storage. For our demo we will select &lt;code&gt;ra3.4xlarge&lt;/code&gt; node type and we will create the cluster with 2 such nodes. &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%2Fdw39q0vj186a1qvjlr6l.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%2Fdw39q0vj186a1qvjlr6l.png" alt="img6" width="800" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After than under &lt;strong&gt;Database configuration&lt;/strong&gt;, we need to provide our database name, port number(where the database will accept the inbound connections), master user name and password. &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%2Fee0ec9xy0uon68ltdo64.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%2Fee0ec9xy0uon68ltdo64.png" alt="img7" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we need to expand the &lt;strong&gt;Cluster permissions&lt;/strong&gt; section and attached an &lt;code&gt;IAM&lt;/code&gt; role. Since our cluster would use Amazon S3 and Amazon SageMaker later on, we need to provide adequate permission so that our Redshift cluster can access data saved in Amazon S3, and Redshift ML can access Amazon SageMaker to build and train the model. We have already created an IAM role namely, &lt;code&gt;RedshiftMLRole&lt;/code&gt;. We can just select the right IAM role from the dropdown and click on &lt;code&gt;Associate IAM role&lt;/code&gt;&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%2Fay5ya2qzm3vdthryymdr.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%2Fay5ya2qzm3vdthryymdr.png" alt="img8" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to create an IAM role with a more restrictive policy, you can use the policy as following. You can also modify this policy to meet your needs.&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%2Fptrforck25cn9zji41gr.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%2Fptrforck25cn9zji41gr.png" alt="img9" width="800" height="1250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, if you would like to connect to this cluster from instances/devices outside the VPC via the cluster endpoint, you would need to enabled &lt;code&gt;Public accessible&lt;/code&gt; option as bellow, but it is not recommended to enable &lt;code&gt;Public accessible&lt;/code&gt;, in our demo we are going to use an &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/private-redshift-cluster-local-machine/" rel="noopener noreferrer"&gt;Amazon EC2 Instance to connect to the cluster via SSH Tunneling&lt;/a&gt;:&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%2Ffws4k0k1bzzs2g6uh9tn.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%2Ffws4k0k1bzzs2g6uh9tn.png" alt="img11" width="800" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just review all the configurations and click on &lt;code&gt;Create cluster&lt;/code&gt; &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%2Fbgcjrxgccko0zy74gd8v.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%2Fbgcjrxgccko0zy74gd8v.png" alt="img12" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Connecting to Redshift Cluster
&lt;/h1&gt;

&lt;p&gt;Next, we can use any tool of our choice to connect to our cluster and we are going to use &lt;a href="https://www.jetbrains.com/datagrip/" rel="noopener noreferrer"&gt;Jetbrains DataGrip&lt;/a&gt;. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Now, if you have created the cluster with &lt;code&gt;Public accessible enabled&lt;/code&gt;, then you can directly connect with the cluster, but since we created the cluster without public access, we are going to use &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/private-redshift-cluster-local-machine/" rel="noopener noreferrer"&gt;Amazon EC2 Instance to connect to the cluster via SSH Tunneling&lt;/a&gt; as mentioned above. And for that we have already created an Amazon EC2 instance in the same region where we created our Redshift cluster and we are going to use the same instance to access the cluster via SSH Tunning.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But before we connect, we need to fist know the &lt;code&gt;JDBC URL&lt;/code&gt; endpoint of our cluster, for that we can click on our cluster and copy the &lt;code&gt;JDBC URL&lt;/code&gt; in our clipboard &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%2Fwl7jajefnwr5de5uetgc.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%2Fwl7jajefnwr5de5uetgc.png" alt="img13" width="716" height="316"&gt;&lt;/a&gt;&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%2Fv8fw5cuza8uyhx07l7b7.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%2Fv8fw5cuza8uyhx07l7b7.png" alt="img14" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we can open Datagrip(or any tool of your choice and connect to the cluster) using the &lt;code&gt;JDBC&lt;/code&gt; URL, &lt;code&gt;user name&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; which we have used while creating the cluster and text the connection. &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%2F75yivh961nrpnr1zajcb.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%2F75yivh961nrpnr1zajcb.png" alt="img15" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then go to the &lt;code&gt;SSN/SSL&lt;/code&gt; option to add the tunnel, this is the place where we need to mention the Amazon EC2 Instance details which we had created earlier and once that is done, we can click on &lt;code&gt;Test Connection&lt;/code&gt; to test if everything is working fine or not. &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%2Fe5wbnl07v579vjteoi2a.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%2Fe5wbnl07v579vjteoi2a.png" alt="img15" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ok, we are now all set to see Redshift ML all in action :) &lt;/p&gt;

&lt;h1&gt;
  
  
  Dataset
&lt;/h1&gt;

&lt;p&gt;We are going to see 3 demos next showing different aspects and functionalities of Redshift ML, which will hopefully help you to get an understanding of different use cases and learn how you make use of Redshift ML irrespective of your background. You may be a &lt;code&gt;Database Engineer/Administrator&lt;/code&gt; or &lt;code&gt;Data Analyst&lt;/code&gt; or an advanced &lt;code&gt;Machine Learning&lt;/code&gt; practitioner, we will cover different demo from the perspective of all these different personas.&lt;/p&gt;

&lt;p&gt;First we need to make sure we upload the dataset on S3(we have uploaded all the dataset in our Amazon S3 bucket, &lt;code&gt;redshift-downloads-2021&lt;/code&gt;). All the dataset can be found inside this &lt;a href="https://github.com/debnsuma/redshiftml-demo.git" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Exercise 1 (Database Engineer's perspective)
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Dataset
&lt;/h3&gt;

&lt;p&gt;In this problem, we are going to use the &lt;a href="https://archive.ics.uci.edu/ml/datasets/bank+marketing" rel="noopener noreferrer"&gt;Bank Marketing Data Set&lt;/a&gt; from &lt;a href="https://archive.ics.uci.edu/ml/index.php" rel="noopener noreferrer"&gt;UCI Machine Learning Repository&lt;/a&gt;. The data is related with direct marketing campaigns of a Portuguese banking institution. The marketing campaigns were based on phone calls. Often, more than one contact to the same client was required, in order to access if the product (bank term deposit) would be ('yes') or not ('no') subscribed.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;objective&lt;/code&gt; is to &lt;em&gt;predict&lt;/em&gt; if the client will subscribe (yes/no) a bank term deposit (variable y). &lt;/p&gt;

&lt;p&gt;The dataset consists of total 20 &lt;code&gt;features/input variable&lt;/code&gt; and one &lt;code&gt;class label/output variable&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Since our dataset is located in Amazon S3, first we need to load the data in table. We can open DataGrip(or whatever SQL Connector you are using) and create the &lt;code&gt;schema&lt;/code&gt; and the &lt;code&gt;table&lt;/code&gt;. Once that is done, we can use &lt;code&gt;COPY&lt;/code&gt; command to load the training data from Amazon S3(&lt;em&gt;bank-additional-full.csv&lt;/em&gt;) to the &lt;code&gt;Redshift&lt;/code&gt; cluster, in the table, &lt;code&gt;client_details&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We need to make sure that colum names of the table matches with the feature sets in the &lt;code&gt;CSV&lt;/code&gt; training dataset file. &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%2Fwfc6y561117y1d97yl5v.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%2Fwfc6y561117y1d97yl5v.png" alt="img16" width="800" height="645"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly we can load the dataset for the testing(&lt;em&gt;bank-additional-inference.csv&lt;/em&gt;) in a separate table, &lt;code&gt;client_details_inference&lt;/code&gt;&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%2Frbvu2yz93wstfh3i55oz.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%2Frbvu2yz93wstfh3i55oz.png" alt="img17" width="800" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Users and Groups
&lt;/h3&gt;

&lt;p&gt;Before we try to create the model, we need to make sure that the user is having the right permission. Just like how Amazon Redshift manages other database objects, such as tables, views, or functions, Amazon Redshift binds &lt;code&gt;model creation&lt;/code&gt; and use to access control mechanisms. There are separate privileges for creating a model running and prediction functions.&lt;/p&gt;

&lt;p&gt;Here are going to create 2 user groups, &lt;code&gt;dbdev_group&lt;/code&gt;(users who will use the model for prediction) and &lt;code&gt;datascience_group&lt;/code&gt;(users who will create the model) and within these groups we will have one user each, &lt;code&gt;dbdev_user&lt;/code&gt; and &lt;code&gt;datascience_user&lt;/code&gt; respectively. &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%2Ftu7qmekjysoe4k5h6h99.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%2Ftu7qmekjysoe4k5h6h99.png" alt="img18" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can grant the appropriate access/permission to the respective group and authorize the user &lt;code&gt;datascience_user&lt;/code&gt; as the current user.&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%2Fy6v9822iphtby94mfrjh.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%2Fy6v9822iphtby94mfrjh.png" alt="img19" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Training (Model Creation)
&lt;/h3&gt;

&lt;p&gt;Finally, now we are all set to create the model using a simple &lt;code&gt;CREATE MODEL&lt;/code&gt; command, it will export the training data, train a model, import the model, and prepare an Amazon Redshift prediction function under the hood.&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%2Fhlkphhnzfgkd8cws3wjv.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%2Fhlkphhnzfgkd8cws3wjv.png" alt="img20" width="800" height="980"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two things to note here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;SELECT&lt;/code&gt; query above creates the training data(input features), i.e. all columns except column &lt;code&gt;y&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;TARGET&lt;/code&gt; clause specifies which column should be used as &lt;code&gt;class label&lt;/code&gt; that the &lt;code&gt;CREATE MODEL&lt;/code&gt; should uses to learn how to predict, i.e. the &lt;code&gt;y&lt;/code&gt; column. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Behind the scene, Amazon Redshift will use Amazon SageMaker Autopilot for &lt;code&gt;training&lt;/code&gt;. At this point, Amazon Redshift will immediately start to use Amazon SageMaker to train and tune the best model for this binary classification problem(as the output or class label can be either &lt;code&gt;yes&lt;/code&gt; or &lt;code&gt;no&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CREATE MODEL&lt;/code&gt; command operates in an &lt;code&gt;asynchronous&lt;/code&gt; mode and it returns upon the export of training data to Amazon S3. As the remaining steps of model training and compilation can take a longer time, it continues to run in the background.&lt;/p&gt;

&lt;p&gt;But we can always check the status of the training using the &lt;code&gt;STV_ML_MODEL_INFO&lt;/code&gt; function. &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%2Fdulejy3oa92p622nh8fo.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%2Fdulejy3oa92p622nh8fo.png" alt="img21" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the training is done, we can use &lt;code&gt;SHOW MODEL ALL&lt;/code&gt; command to see all the models which we have access to:&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%2Fz17dkpixhvpqer49du7j.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%2Fz17dkpixhvpqer49du7j.png" alt="img22" width="748" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can also see some more details about the model, e.g. model performance(like accuracy, F1 score, MSE, etc. depending on the problem type), model type, problem type, etc. &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%2Fhd4zekwwu1rn7bmt55jd.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%2Fhd4zekwwu1rn7bmt55jd.png" alt="img23" width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Accuracy of the Model and Prediction/Inference
&lt;/h3&gt;

&lt;p&gt;Now that we have the new SQL function, &lt;code&gt;func_model_bank_marketing2&lt;/code&gt;, we can use the same function for prediction. But before we do so, let's first grant the appropriate access/permission to the &lt;code&gt;dbdev_group&lt;/code&gt;so that the &lt;code&gt;dbdev_user&lt;/code&gt; can use the function for prediction. Once that is done we can change the authorization to &lt;code&gt;dbdev_user&lt;/code&gt; as we expect that the prediction operation to be executed by the database engineer or the data analyst and not necessarily by only the data scientists in the organization. &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%2Fqc4s8lpxcl9n0z7e71pk.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%2Fqc4s8lpxcl9n0z7e71pk.png" alt="img24" width="800" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First let's try to see what's the accuracy of out model, using the test data which we have in the &lt;code&gt;client_details_inference&lt;/code&gt; table.  &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%2Ffukkxkm4pv1n11m4avyl.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%2Ffukkxkm4pv1n11m4avyl.png" alt="img25" width="800" height="710"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see the accuracy is around &lt;code&gt;94%&lt;/code&gt;, which is not all that bad considering the small dataset we used for this problem, but we can see how easily we use simple SQL query to &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;train&lt;/code&gt; and &lt;code&gt;deploy&lt;/code&gt; our ML models using Redshift ML. &lt;/p&gt;

&lt;p&gt;And finally let's try to do some prediction using this same model function &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%2Fh3j0ml2sgfp24v6kcftg.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%2Fh3j0ml2sgfp24v6kcftg.png" alt="img26" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl"&gt;Part 2&lt;/a&gt; of this tutorial series we will try to cover few more advanced functionalities, and those would be from a Data Analyst or any expert Data Scientist viewpoint, wherein you can define many advanced options, like &lt;code&gt;model type&lt;/code&gt;, &lt;code&gt;hyperparameters&lt;/code&gt;, &lt;code&gt;objective function&lt;/code&gt;, &lt;code&gt;pre-processors&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;But before we move on to the &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl"&gt;Part 2&lt;/a&gt;, let's spend some time to underhand the &lt;code&gt;costs&lt;/code&gt; consideration using Redshift ML and how you can control it. &lt;/p&gt;

&lt;h3&gt;
  
  
  Cost and Redshift ML
&lt;/h3&gt;

&lt;p&gt;As Amazon Redshift ML use the existing cluster resources for prediction, there is no additional Amazon Redshift charges. That means, there is no additional Amazon Redshift charge for creating or using a model,&lt;br&gt;
and as prediction happens locally in your Amazon Redshift cluster, you don't have to pay extra. &lt;/p&gt;

&lt;p&gt;But, as we learnt that Amazon Redshift ML uses Amazon SageMaker for training our model, which does have an additional associated cost. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;CREATE MODEL&lt;/code&gt; statement uses Amazon SageMaker as we have seen before, and that incurs an additional cost. The cost increases with the&lt;code&gt;number of cells&lt;/code&gt; in your training data. The number of cells is proportional to &lt;code&gt;number of records&lt;/code&gt; (in the training query or table) &lt;em&gt;times&lt;/em&gt; the &lt;code&gt;number of columns&lt;/code&gt;. For example, when a &lt;code&gt;SELECT&lt;/code&gt; query of the &lt;code&gt;CREATE MODEL&lt;/code&gt; statement creates 100,000 records and 50 columns, then the &lt;code&gt;number of cells&lt;/code&gt; it creates is 500,0000.&lt;/p&gt;

&lt;p&gt;One way to control the cost is by using two option &lt;code&gt;MAX_CELL&lt;/code&gt; and &lt;code&gt;MAX_RUNTIME&lt;/code&gt; in the &lt;code&gt;CREATE MODEL&lt;/code&gt; command statement. Where &lt;code&gt;MAX_RUNTIME&lt;/code&gt; specifies the maximum amount of time the training can take in SageMaker when the &lt;code&gt;AUTO ON/OFF&lt;/code&gt; option is used. Although training jobs can complete sooner than MAX_RUNTIME, depending on the size of the dataset. But there are additional works which Amazon Redshift performs after the model is trained, like compiling and installing the model in your cluster. So, the &lt;code&gt;CREATE MODEL&lt;/code&gt; command can take a little longer time then then &lt;code&gt;MAX_RUNTIME&lt;/code&gt; to complete. This option can be used to limit the cost as it controls the time to be used by Amazon SageMaker to train your model. &lt;/p&gt;

&lt;p&gt;Under the hood, when you run &lt;code&gt;CREATE MODEL&lt;/code&gt; with &lt;code&gt;AUTO ON&lt;/code&gt;, Amazon Redshift ML uses &lt;code&gt;SageMaker Autopilot&lt;/code&gt; which automatically explores all the different models(or candidates) to find the best one. &lt;code&gt;MAX_RUNTIME&lt;/code&gt; limits the amount of time and computation spent and if &lt;code&gt;MAX_RUNTIME&lt;/code&gt; is set too low, there might not be enough time to explore even one single candidate. And you would get an error saying, "&lt;em&gt;Autopilot candidate has no models&lt;/em&gt;" and in that case you would need to re-run the &lt;code&gt;CREATE MODEL&lt;/code&gt; with a larger &lt;code&gt;MAX_RUNTIME&lt;/code&gt; value. &lt;/p&gt;

&lt;p&gt;One another way to control cost for training (&lt;em&gt;which may not be a good idea always as it would affect the model accuracy&lt;/em&gt;), is by specifying a smaller &lt;code&gt;MAX_CELLS&lt;/code&gt; value when you run the &lt;code&gt;CREATE MODEL&lt;/code&gt; command.  MAX_CELLS limits the number of cells, and thus the number of training examples used to train your model. &lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;MAX_CELLS&lt;/code&gt; is set to 1 million cells. Reducing MAX_CELLS reduces the number of rows from the result of the SELECT query in &lt;code&gt;CREATE MODEL&lt;/code&gt; that Amazon Redshift exports and sends to SageMaker to train a model. Reducing MAX_CELLS thus reduces the size of the dataset used to train models both with AUTO ON and AUTO OFF. This approach helps reduce the costs and time to train models.&lt;/p&gt;

&lt;p&gt;In summary, by increasing &lt;code&gt;MAX_RUNTIME&lt;/code&gt; and &lt;code&gt;MAX_CELLS&lt;/code&gt; we can often improve the model quality as it allows Amazon SageMaker to explore more candidates and it would have more training data to train better models. &lt;/p&gt;

&lt;h1&gt;
  
  
  What next...
&lt;/h1&gt;

&lt;p&gt;So, in the tutorial we learnt a bit about, what Amazon Redshift is and how you can create, train and deploy a ML model using familiar SQL query from a Database Engineer's/Administrator's perspective, in the next &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl"&gt;part&lt;/a&gt; we will explore little bit more on how you can make use of Amazon Redshift ML if you are an advanced data analyst or a data scientist and shall explore some advanced options, which it has to offer. &lt;/p&gt;

&lt;h1&gt;
  
  
  Resources
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt; : &lt;a href="https://github.com/debnsuma/redshiftml-demo.git" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blog&lt;/strong&gt; : &lt;a href="https://dev.to/aws/amazon-redshift-ml-machine-learning-in-sql-style-part-2-gl"&gt;Amazon Redshift ML - Machine Learning in SQL Style (Part-2)&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/redshift/features/redshift-ml/" rel="noopener noreferrer"&gt;Using machine learning in Amazon Redshift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Book&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.amazon.com/Learn-Amazon-SageMaker-developers-scientists-ebook/dp/B08FMWJXGN" rel="noopener noreferrer"&gt;Learn SageMaker&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Videos&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=8zHh2DoQZBs" rel="noopener noreferrer"&gt;AWS on Air 2020: AWS What’s Next ft. Amazon Redshift Machine Learning&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=3BN1w8JUtD4" rel="noopener noreferrer"&gt;AWS re:Invent 2020: Introducing Amazon Redshift Machine Learning&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>datascience</category>
      <category>database</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>An Introduction to Decision Tree and Ensemble Methods – Part 1</title>
      <dc:creator>Suman Debnath</dc:creator>
      <pubDate>Thu, 09 Apr 2020 13:01:38 +0000</pubDate>
      <link>https://dev.to/aws/an-introduction-to-decision-tree-and-ensemble-methods-part-1-24p0</link>
      <guid>https://dev.to/aws/an-introduction-to-decision-tree-and-ensemble-methods-part-1-24p0</guid>
      <description>&lt;p&gt;In this day and age, there is a lot of buzz around Machine Learning(ML) and Artificial Intelligence(AI). And why not, after all, we all are consumers of ML directly or indirectly; irrespective of our professions. AI/ML is a fascinating field, generates a whole lot of excitement around it, and rightly so. In this tutorial series, we will try to explore and demystify the complicated world of &lt;code&gt;{math, equations, and theory}&lt;/code&gt; that functions in tandem to bring out the "magic" which we experience on many application(s)/software(s). The idea is to discuss AI/ML algorithms in detail, implement it from scratch(wherever applicable), and enable the readers to answer &lt;em&gt;&lt;code&gt;"How?"&lt;/code&gt;&lt;/em&gt; rather than &lt;em&gt;&lt;code&gt;"What?"&lt;/code&gt;&lt;/em&gt;. And while we discuss all of these, we shall demonstrate everything on AWS platform using different services as applicable. Having said that, I am a learner as most of you; trying to get a better understanding of this field with each passing day and I just wish to share my learning as I go along with a broader group . Your inputs/feedback are always welcome, anything that would help me improve this process. &lt;/p&gt;

&lt;p&gt;But before we go ahead, I would also like to thank my teacher, Srikanth Varma Sir, for guiding me and 100s of thousands of students like me across the globe. Without him, I wouldn't have dreamt of getting into this wonderful world of Machine Learning. This write up is completely based on the class I have attended from his course at &lt;a href="https://www.appliedaicourse.com/" rel="noopener noreferrer"&gt;AppliedAI&lt;/a&gt; on Decision Tree.  &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;An Introduction to Decision Tree&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;In this tutorial, we will explore one of the most rampantly used and fundamental Machine Learning model, &lt;em&gt;Decision Tree(DT)&lt;/em&gt;. &lt;em&gt;DT&lt;/em&gt; is a very powerful model which can help us to classify labelled data and make predictions. It also enlightens us with lots of information about the data and most importantly, it's effortlessly easy to &lt;em&gt;interpret&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If you are a software engineer, you would probably know &lt;code&gt;“if-else”&lt;/code&gt; conditions, and we all love it, because it’s very simple to understand, imagine and code. A decision tree can be thought of nothing but a &lt;code&gt;“nested if-else classifier”&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Decision tree, is one of the classifiers we have in the world of machine learning, which closely resembles with human reasoning. It is also one of model we have, which comes under the category of supervised machine learning. In &lt;code&gt;supervised&lt;/code&gt; machine learning, we are always given with the &lt;code&gt;input data&lt;/code&gt; (also referred as features or independent features) and &lt;code&gt;class labels&lt;/code&gt;(also referred as target feature or dependent feature). &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Supervised learning&lt;/strong&gt;&lt;/em&gt; is the machine learning task of learning a function that maps an input to an output based on example input-output pairs. It infers a function from labeled training data consisting of a set of training examples. In supervised learning, each example is a pair consisting of an input object (typically a vector) and a desired output value.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s try to understand this with a simple example, suppose we have a data set of 50 fruits, out of which few are lemons and few are apples, and we are given fruit colour and fruit size as the input feature(so these are our 2 independent features). &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%2Fg6zz6dhm76mvm3x5lpqd.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%2Fg6zz6dhm76mvm3x5lpqd.png" alt="img1" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The decision tree for this problem, might look like this:&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%2F6qtrxcmf83xwged1w1vz.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%2F6qtrxcmf83xwged1w1vz.png" alt="img2" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the question is, given a dataset, how can we build a tree like this ? To understand this, we need to look into the "math" behind this, which we will see in the next section. But before that, let's try to learn some key terminologies we must be aware of to work with Decision Tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NODE&lt;/code&gt;: Each time we ask a question or make a decision stump, we represent the same as a NODE. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ROOT&lt;/code&gt;: The topmost node of the tree which we start questioning with. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;INTERIOR&lt;/code&gt;: Any node, except the ROOT node, where we &lt;em&gt;again&lt;/em&gt; ask a question. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;LEAF&lt;/code&gt;: When we reach a point where we don’t ask a question, but instead make a decision, we call it as LEAF node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So here is the general DT structure example:&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%2Fhx75abm9tdwdjce8cpbz.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%2Fhx75abm9tdwdjce8cpbz.png" alt="img3" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Decision trees&lt;/strong&gt;&lt;/em&gt; are &lt;code&gt;supervised&lt;/code&gt; learning algorithms, which means, we need to have labelled dataset and it can be used for both, classification and regression tasks, which means we can have it for categorical data or continuous data. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Training flow of a Decision Tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepare the labelled data set, with &lt;code&gt;independent feature&lt;/code&gt;{1, 2, 3, …, n} and &lt;code&gt;dependent feature&lt;/code&gt;(target or class label). &lt;/li&gt;
&lt;li&gt;Try to pick the best feature as the &lt;code&gt;root&lt;/code&gt; node and thereafter, use intelligent strategies to split the nodes into multiple branches.
&lt;/li&gt;
&lt;li&gt;Grow the tree until we get a &lt;code&gt;stopping&lt;/code&gt; criteria, i.e. the leaf node which would be the actual prediction when we make any query or ask for prediction. &lt;/li&gt;
&lt;li&gt;Pass through the prediction data query through the tree until we arrive at some &lt;code&gt;leaf node&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Once we get the leaf node, we have the prediction!! :)&lt;/li&gt;
&lt;/ul&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%2F4v3y2srpa6z7knsduizv.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%2F4v3y2srpa6z7knsduizv.png" alt="img4" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Math behind Decision Tree&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Now that we know how a Decision Tree looks like, next step to think about is(&lt;em&gt;and it’s the most important task to accomplish&lt;/em&gt;), how can we go from training data to a decision tree ? And to understand this, we need to go over a bunch of very important concepts. &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Entropy&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Entropy is a very interesting concept in the field of &lt;a href="https://en.wikipedia.org/wiki/Information_theory" rel="noopener noreferrer"&gt;Information Theory&lt;/a&gt;. It is the notion of the &lt;em&gt;impurity&lt;/em&gt; of the data, now what is this new term &lt;code&gt;impurity&lt;/code&gt; of the data?&lt;/p&gt;

&lt;p&gt;Let’s take an example, we have this node:&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%2Fv7wf2zzhkxdvfg4uf36z.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%2Fv7wf2zzhkxdvfg4uf36z.png" alt="img5" width="546" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can say that, this node is &lt;code&gt;pure&lt;/code&gt; because there is only one class, no ambiguity in the class label(i.e. it’s all APPLE), Now, let’s say this node:&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%2Fmxhesramxacqm63b9wmp.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%2Fmxhesramxacqm63b9wmp.png" alt="img6" width="552" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can say, that it's little &lt;code&gt;less pure&lt;/code&gt; w.r.t to the previous node, as there is some small amount of ambiguity that exists in the class label(as few LEMONs are present, along with APPLE). And finally, let’s see this node:&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%2Fdi1lpylp4i4o5bsnj0oq.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%2Fdi1lpylp4i4o5bsnj0oq.png" alt="img7" width="558" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is very much an &lt;code&gt;impure&lt;/code&gt; node, as we have mixed classes(red APPLE, green APPLE, and yellow LEMON). &lt;/p&gt;

&lt;p&gt;Now, let’s go back to the definition of &lt;code&gt;Entropy&lt;/code&gt;, it’s the notion of impurity of a node, in other words, the more the impurity the more the entropy and vice versa. &lt;/p&gt;

&lt;p&gt;Let’s say we have Random Variable, X, where x can be x1, x2, x3, x4…xn&lt;br&gt;
Then, mathematically, Entropy can be defined as(also known as Shannon's entropy) this:&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%2Fd8wpssd6xk2z95zwcfwq.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%2Fd8wpssd6xk2z95zwcfwq.png" alt="img8" width="478" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;where, &lt;br&gt;
k = ranges from 1 through n&lt;br&gt;
H(x) = entropy of x&lt;br&gt;
P(k) = Probability of random variable X when (X = k)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, let’s take an example to understand it little better, &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%2Fxdfs92mejrjcpmlwymoe.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%2Fxdfs92mejrjcpmlwymoe.png" alt="img9" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this dataset(D), Play Ball is the &lt;code&gt;target&lt;/code&gt; class, and the random variable, X. And it can take only two values, &lt;em&gt;“Yes”&lt;/em&gt; or &lt;em&gt;“No”&lt;/em&gt;. So, &lt;/p&gt;

&lt;p&gt;&lt;code&gt;P(k=Yes)&lt;/code&gt; =&amp;gt; 9/14 = 0.64&lt;br&gt;
&lt;code&gt;P(k=No)&lt;/code&gt;  =&amp;gt; 5/14 = 0.36&lt;/p&gt;

&lt;p&gt;Therefore, the Entropy of “Play Ball” on the dataset(D), would be:&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%2Fswbqnqwg5o3gmlp8a6yy.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%2Fswbqnqwg5o3gmlp8a6yy.png" alt="img11" width="800" height="49"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we think intuitively, what this essentially means is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Higher&lt;/code&gt; the Entropy, &lt;code&gt;more impure&lt;/code&gt; the dataset is. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Lower&lt;/code&gt; the Entropy, &lt;code&gt;more pure&lt;/code&gt; the dataset is. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Information Gain(IG)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that we have an idea of what an &lt;code&gt;Entropy&lt;/code&gt; is, the next important concept to look into is &lt;code&gt;Information Gain(IG)&lt;/code&gt;.  Let’s continue with the same example as above, where we have the Entropy, H(“Play Ball”) or in other words, Entropy of the target label, “Play Ball” is 0.94. Now, let’s say we split the dataset with “Outlook” feature set, then our dataset would look like this:&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%2Fjrmv0q3q4bajs2kph3nd.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%2Fjrmv0q3q4bajs2kph3nd.png" alt="img12" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we get 3 small sub-datasets(D1, D2, and D3), based on the different values we have for the feature “Outlook”(i.e. Rainy, Overcast and Sunny). So, if now compute the &lt;code&gt;Entropy&lt;/code&gt; of each of this small sub-dataset on the same target class “Play ball”, it would be:&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%2Ftz0ze0onap69h3wwi5go.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%2Ftz0ze0onap69h3wwi5go.png" alt="img13" width="800" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the &lt;code&gt;Weighted Entropy&lt;/code&gt; after breaking the dataset to D1, D2 and D3 would be:&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%2Fc2esrr0abz5bmhj51o5g.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%2Fc2esrr0abz5bmhj51o5g.png" alt="img14" width="800" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, the Information Gain of the dataset D, when we break it based on feature, Outlook, would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Information Gain(Outlook)&lt;/strong&gt;= &lt;em&gt;Entropy(D) − Weighted Entropy after breaking the dataset&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&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%2Fv2sdlghl4dq82qkz0njk.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%2Fv2sdlghl4dq82qkz0njk.png" alt="img15" width="800" height="99"&gt;&lt;/a&gt;&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%2Fec8kkpn8r1c0gbhp2hsz.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%2Fec8kkpn8r1c0gbhp2hsz.png" alt="img17" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, we can find the IG based on other features as well(for &lt;code&gt;Temperature&lt;/code&gt;, &lt;code&gt;Humidity&lt;/code&gt; and  &lt;code&gt;Windy&lt;/code&gt;)&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%2Fei7c2hc0jij4n6dz6xuc.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%2Fei7c2hc0jij4n6dz6xuc.png" alt="img16" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, if we have the information gain of all these 4 features, and it’s very clear that, the information gain of the feature “Outlook” is the largest, which indirectly says that this feature(“Outlook”) gives us the maximum amount of information about the target class(“Play ball”). &lt;/p&gt;

&lt;p&gt;Hence, Decision Tree would use this feature as the &lt;em&gt;ROOT&lt;/em&gt; node of the tree. And once the data is split, we need to further check each of the small sub tree and perform the same activity and decide the next feature which has the highest IG, so that we can split the dataset further to get to leaf node. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;How to build a Tree&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;With the understanding of what is &lt;code&gt;Entropy&lt;/code&gt; and &lt;code&gt;IG&lt;/code&gt;, we can build a tree, and here is the algorithmic steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First the entropy of the total dataset is calculated for the target label/class.&lt;/li&gt;
&lt;li&gt;The dataset is then split on different features. &lt;/li&gt;
&lt;li&gt;The entropy for each branch is calculated. Then it is added proportionally, to get total weighted entropy for the split.&lt;/li&gt;
&lt;li&gt;The resulting entropy is subtracted from the entropy before the split.&lt;/li&gt;
&lt;li&gt;The result is the Information Gain.&lt;/li&gt;
&lt;li&gt;The feature that yields the largest IG is chosen for the decision node.&lt;/li&gt;
&lt;li&gt;Repeat step #2 to #6, for each subset of the data(for each internal node) until:

&lt;ul&gt;
&lt;li&gt;All the dependent features are exhausted. &lt;/li&gt;
&lt;li&gt;The stopping criteria are met.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Few of the stopping criteria used are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no. of levels of tree from the root node(or in other words, depth of the tree)&lt;/li&gt;
&lt;li&gt;Minimum no. of observations in the parent/child node(e.g. 10% of the training data)&lt;/li&gt;
&lt;li&gt;Minimum reduction of impurity index &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Algorithm behind decision tree&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;So far, we have discussed about &lt;code&gt;Entropy&lt;/code&gt; as one of the ways to find the impurity of a node, but there are other techniques available to split the data, like &lt;code&gt;Gini Impurity&lt;/code&gt;, &lt;code&gt;Chi-Square&lt;/code&gt;, &lt;code&gt;Variance&lt;/code&gt;, &lt;code&gt;etc.&lt;/code&gt;. However, we have different algorithms to implement a Decision Tree model, and each uses different techniques to identify the impurity of a node, and hence the split. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ID3(Iterative Dichotomiser 3)&lt;/code&gt; algorithm - &lt;em&gt;uses&lt;/em&gt; Entropy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CART&lt;/code&gt; algorithm - &lt;em&gt;uses&lt;/em&gt; Gini Impurity Index&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;C4.5&lt;/code&gt; - &lt;em&gt;uses&lt;/em&gt; Gain Ratio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thankfully, we do not have to do all this(like calculating Entropy, IG, implement ID3, etc.), we have lots of libraries/packages available in Python which we can use to solve a problem with decision tree. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Problem&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Here is the &lt;a href="https://archive.ics.uci.edu/ml/machine-learning-databases/00422/" rel="noopener noreferrer"&gt;dataset&lt;/a&gt;. The data set contains wifi signal strength observed from 7 wifi devices on a smartphone collected in indoor space(4 different rooms)? The task is to predict the location(which room) from wifi signal strength. Form more details check &lt;a href="http://archive.ics.uci.edu/ml/datasets/Wireless+Indoor+Localization" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Amazon SageMaker Notebook&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before we get into code, we would spin an &lt;code&gt;Amazon SageMaker Notebook&lt;/code&gt;, it’s a fully managed ML compute instance running the Jupyter Notebook App. It manages creating the instance and related resources for us, we are going to use Amazon SageMaker Notebook, rather than using local Jupyter-Notebook on our laptop(and we will later see why?)&lt;/p&gt;

&lt;p&gt;We will use Jupyter notebooks within our notebook instance to prepare and process data, write code to train models, deploy models to Amazon SageMaker hosting, and test or validate your models. For this tutorial, since we are going to have a small dataset, we will not be deploying the model, but going forward for the upcoming tutorials we are going to solve various complex problem wherein we would deploy the model as well. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Login to &lt;code&gt;AWS Console&lt;/code&gt; &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search of &lt;code&gt;SageMaker&lt;/code&gt; under Find Services search bar &lt;br&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%2F1600l332o7d32zic7q6p.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%2F1600l332o7d32zic7q6p.png" alt="img2a" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on the side menu, &lt;code&gt;Notebook&lt;/code&gt; -&amp;gt; &lt;code&gt;Notebook Instances&lt;/code&gt; and then click on &lt;code&gt;Create notebook Instance&lt;/code&gt; &lt;br&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%2F5xgze7weru8cq5vykk54.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%2F5xgze7weru8cq5vykk54.png" alt="img3a" width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Specify the instance type, and click &lt;code&gt;Create notebook instance&lt;/code&gt;. &lt;br&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%2Fzgb90bvdg97woqxxzkkv.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%2Fzgb90bvdg97woqxxzkkv.png" alt="img4a" width="760" height="800"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Wait for the instance till the Status changes from &lt;code&gt;Pending&lt;/code&gt; to &lt;code&gt;InService&lt;/code&gt; &lt;br&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%2Fplgambcszgc8e79feoww.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%2Fplgambcszgc8e79feoww.png" alt="img5a" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once its &lt;code&gt;InService&lt;/code&gt;, click on &lt;code&gt;Open Jupyter&lt;/code&gt;&lt;br&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%2Fkrqhfe249asx0e9ulfzc.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%2Fkrqhfe249asx0e9ulfzc.png" alt="img6a" width="800" height="103"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, now our &lt;code&gt;Jupyter Notebook&lt;/code&gt; is up and running. One of the best part of SageMaker Notebook is it being completely managed and all the different framework comes out of the box, for example, if we click on &lt;code&gt;New&lt;/code&gt; and try to create a new notebook, we will see list of different kernels available, we don’t have to worry about installing, maintaining the updates, etc. &lt;/p&gt;

&lt;p&gt;OK, we are all set now, lets go back the problem statement we have in hand and start coding. &lt;br&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%2Fjha6xphx2zzq7i0dajjx.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%2Fjha6xphx2zzq7i0dajjx.png" alt="img7a" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Loading the necessary modules&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lets load the modules we will need to work with this problem, we will be using &lt;a href="https://scikit-learn.org/stable/" rel="noopener noreferrer"&gt;scikit-learn&lt;/a&gt; machine learning library&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%2Fe523r6v0jyrfgtase1c8.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%2Fe523r6v0jyrfgtase1c8.png" alt="code1" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Decision Tree Classifier&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let's create a small function which will return a decision tree classifier&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%2F830ndrvesf0hoezv8pur.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%2F830ndrvesf0hoezv8pur.png" alt="code2" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, the function takes 2 arguments, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;X_train&lt;/code&gt;: Input or Independent Features and &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;y_train&lt;/code&gt;: Class or Target Label &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then we use &lt;a href="https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html" rel="noopener noreferrer"&gt;DecisionTreeClassifier&lt;/a&gt; classifier from scikit-learn library, this function takes many arguments(which are also commonly know as hyperparameters), and here we are using one of them, &lt;code&gt;criterion&lt;/code&gt;: The function to measure the quality of a split. Supported criteria are “gini” for the gini impurity and “entropy” for the information gain. &lt;/p&gt;

&lt;p&gt;And this function returns &lt;code&gt;clf_tree&lt;/code&gt;: the decision tree classifier which we will be using for inference(prediction) later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Load the dataset&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Lets load the dataset (&lt;code&gt;wifi_localization.txt&lt;/code&gt;)&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%2Fppv7509lsdjuloumlkdz.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%2Fppv7509lsdjuloumlkdz.png" alt="code3" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, after loading the data in a &lt;code&gt;df&lt;/code&gt;: Pandas DataFrame, we insert the column names and separates the Input Features(&lt;code&gt;X&lt;/code&gt; DataFrame) and Target Label(&lt;code&gt;Y&lt;/code&gt; DataFrame)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Splitting the dataset&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, we will split the whole dataset into training and testing(we will use 20% of the total data points for testing),&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%2Fvhh7o258rom5mhzx2cov.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%2Fvhh7o258rom5mhzx2cov.png" alt="code4" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can see the first 5 data points:&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%2Fiktizy9wz57ot8j2x3ie.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%2Fiktizy9wz57ot8j2x3ie.png" alt="img18" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Decision Tree Classifier&lt;/strong&gt;
&lt;/h3&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%2Fi2v5qhe63l3381ux0cdn.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%2Fi2v5qhe63l3381ux0cdn.png" alt="code5" width="800" height="74"&gt;&lt;/a&gt;&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%2F8aq44ouur3gug6sq0va5.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%2F8aq44ouur3gug6sq0va5.png" alt="img19" width="800" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see that this classifier can be tuned with many parameters(often times, its called hyper-parameters. For more details on what each hyper parameters mean, we can refer to the &lt;a href="https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have used one of the hyper-parameter here &lt;code&gt;criterion&lt;/code&gt;, as "entropy", which mean that the classifier will use entropy to calculate the IG, which would be ultimately used to split the data in the background. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Predicting the result on the test data&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we can use our Decision Tree Classifier object &lt;code&gt;clf_tree&lt;/code&gt; to make some prediction on my testing data(&lt;code&gt;X_test&lt;/code&gt;) &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%2Fiv8wqjkrpbel4zfr28sh.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%2Fiv8wqjkrpbel4zfr28sh.png" alt="code6" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Evaluating the Performance&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now, that we got the prediction(&lt;code&gt;y_pred&lt;/code&gt;), we can validate it with the actual labels (&lt;code&gt;y_test&lt;/code&gt;) of this test data. &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%2Fa0syst1b8kkf6mwcm57i.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%2Fa0syst1b8kkf6mwcm57i.png" alt="code7" width="800" height="243"&gt;&lt;/a&gt;&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%2Fu7yx8lokgohufutkgeb7.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%2Fu7yx8lokgohufutkgeb7.png" alt="img20" width="713" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We did a lot in these last few lines of code, and we saw some new terms, &lt;code&gt;accuracy&lt;/code&gt;, &lt;code&gt;precision&lt;/code&gt;, &lt;code&gt;recall&lt;/code&gt;, &lt;code&gt;f1-score&lt;/code&gt; and &lt;code&gt;confusion matrix&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;These all were Model Performance Metrics, we will have one tutorial dedicated to different Model Performance Metrics as we have many and not only these which are mentioned here, but for now, we can think of these as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;accuracy&lt;/code&gt; : It simply measures, how accurately the model predicted, e.g. if we have 10 test data points, and out of 10, only 8 data points are predicted correctly by the classifier, then the accuracy would be 80%, which also means accuracy can lie between 0 to 1&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;precision&lt;/code&gt;: The precision is the ratio &lt;code&gt;tp / (tp + fp)&lt;/code&gt; where tp is the number of true positives and fp the number of false positives. The precision is intuitively the ability of the classifier not to label as positive a sample that is negative.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recall&lt;/code&gt;: The recall is the ratio &lt;code&gt;tp / (tp + fn)&lt;/code&gt; where tp is the number of true positives and fn the number of false negatives. The recall is intuitively the ability of the classifier to find all the positive samples.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f1-score&lt;/code&gt;: The F1 score can be interpreted as a weighted average of the precision and recall, where an F1 score reaches its best value at 1 and worst score at 0. The relative contribution of precision and recall to the F1 score are equal. Mathematically it is defined by: &lt;code&gt;2 * (precision * recall) / (precision + recall)&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Visualize A Decision Tree&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Finally, we will try to visualize how our Decision Tree looks like, and we can do so, using a library &lt;a href="https://pypi.org/project/graphviz/" rel="noopener noreferrer"&gt;&lt;code&gt;graphviz&lt;/code&gt;&lt;/a&gt;&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%2F3eydeyfoj6q5eyv22ulz.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%2F3eydeyfoj6q5eyv22ulz.png" alt="code8" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is finally how the tree from the above classifier would look like. You can also download it from &lt;a href="https://myblog-imgs.s3.amazonaws.com/01_DT/img/DT_Graph.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;&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%2F2d2u6is7778j8uhf0g94.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%2F2d2u6is7778j8uhf0g94.png" alt="img21" width="779" height="673"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we will explore some other algorithm and solve some problem. You may like to get the code/jupyter-notebook from &lt;a href="https://github.com/debnsuma/AI-ML-Algo2020/tree/master/01.Decision_Tree" rel="noopener noreferrer"&gt;git repo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Reference&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You may like to visit the below mentioned course, books and source links which were referred to for the tutorial:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Course&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.appliedaicourse.com/" rel="noopener noreferrer"&gt;AppliedAI&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Books:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="http://profsite.um.ac.ir/~monsefi/machine-learning/pdf/Machine-Learning-Tom-Mitchell.pdf" rel="noopener noreferrer"&gt;Machine Learning by Tom Mitchell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.amazon.in/Python-Machine-Learning-scikit-learn-TensorFlow-ebook/dp/B0742K7HYF" rel="noopener noreferrer"&gt;Python Machine Learning by Sebastian Raschka, Vahid Mirjalili&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Blogs:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://python-course.eu/" rel="noopener noreferrer"&gt;Machine Learning with Python &lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/" rel="noopener noreferrer"&gt;Towards Data Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.analyticsvidhya.com/blog/?utm_source=home_blog_navbar" rel="noopener noreferrer"&gt;Analytics Vidya&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Amazon SageMaker:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/sagemaker-dg.pdf" rel="noopener noreferrer"&gt;Amazon SageMaker Developers Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/sagemaker/latest/dg/nbi.html" rel="noopener noreferrer"&gt;Amazon SageMaker Notebook Instances&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
