Sales Opportunity Score Dashboard

Building a Relationship Manager's Best Friend With Python

Imagine your goal is to empower sales people to make the best decisions possible: what would that solution look like? For several AI Squared customers, that has been combining analytics such as propensity scores and product recommendations, as well as useful information about sales prospects, into a single dashboard that is then integrated into a CRM tool.

This example shows you how to build this dashboard in the no-code editor in the AI Squared platform. For an overview of how to build this same use case with our no-code environment in the AI Squared platform, click here:

Sales Opportunity Score Dashboard

Here's a view of the dashboard that we are building in this example:

Importing Packages

Because the data to be used for the Reverse ML Workflow is already stored in S3, we only need to import the config subpackage from the aisquared package to complete this tutorial.

# import the aisquared package
from aisquared import config

Defining the Workflow

Now that we have imported the required package, let's dive head first into completing this workflow. We are going to need to perform the following steps:

  • Create a harvester which looks for customer names in the webpage

  • Connect the webpage and the text we have harvested to the S3 bucket for query using the ReverseMLWorkflow

  • Render results in a set of steps to create the dashboard using the data related to the customer

Harvester

The first step of the AI Squared process is harvesting - pulling information from the end-user environment to help define the rest of the integration.

  • The first step in the Harvesting phase is to instantiate an object from the appropriate harvesting class, based on our predictive model. In this particular scenario, we are dealing with text data, and hence we will use the Text Harvester class from our harvesting options.

  • Subsequent to the selection of the Harvester class, the next step is to define a regular expression (regex) to extract the Lead first name and last name from the dataset. The SOS dashboard will be determined based on this Lead name. The regular expression will function as an extractor for this specific pattern within the data.

  • The format of the Lead name would be first name and last name; therefore, we have given two examples of the name format where we are supposed to specify the regex pattern.

# Create the harvester
harvester = config.harvesting.TextHarvester(
    how = 'regex',
    regex = 'Alice Alison|Bob Bobson|Charles Charleston|David Davidson|Eric Ercison|Frederick Frederickson|Georg Georges|Hilda Henrick|Igor Igloo|John Johnson',
    limit = 1
)

Analytic

For this example, we are making use of 2 machine learning models (computing the propensity score and product recommendations) and a data source containing static information about the prospective customer. For simplicity, we consider the 2 models as running periodic batch inference, with their outputs merged with the static data source, resulting in a single CSV file in S3 that we need to pull information from.

  • In the Analytics stage, we instantiate an object from the 'Reverse ML' workflow, This helps us understand how our model makes decisions.

  • We set the data input type as 'Text', in accordance with the data type we're working with. This makes sure that the Analytics class processes the input data appropriately.

  • We then supply the bucket name parameter. This refers to the name of the specific cloud storage bucket where our data file is stored.

  • In our model, we use a specific column designated as 'Lead_Name'. This column serves as a key identifier as it contains the first and last names of the leads, forming the primary basis for generating the SOS dashboard.

    • Note that in the harvesting step we are regexing customer names - we use the identified customer name to map to the row in the data source we are connecting to with ReverseML.

  • We can then implement filters if needed. The filters can be added by specifying the column name along with its corresponding value. The function of these filters is to include or exclude certain data points during the data processing phase in the analytic stage.

# The analytic in this workflow is a ReverseMLWorkflow
analytic = config.analytic.ReverseMLWorkflow(
    column = 'Lead_Name',
    period = 1,
    filenames = 'SOS_Sample_for_Dashboard_edit9.csv',
    input_type = 'text',
    bucket = 'ai2-demo-bucket',
    filter_type = 'group',
    filter_by_columns = []
)

Pre- and Post-Processing

No pre or post-processessing is required for this use case (that is more typical for machine learning use cases with online inference. You can set these to None.

# No preprocesser or postprocesser is required for this dashboard
preprocesser = None
postprocesser = None

Rendering

We'll now make use of the container rendering class, as well as several of the AI Squared rendering components, to visualize our data.

  • During the rendering phase, outputs generated from our model are transposed into the browser interface. Here, the class type is utilized to decide the form of rendering, specifically, we opt for Word Rendering in this context. This will ultimately decide the location of model predictions and their visual representation on the interface.

  • In this particular scenario, a dashboard will be created to visualize the results. As per the above image, various containers were added to include various data results for example, under Email Stats container, email sent, emails opened, emails bounced back data will be displayed. There will also be tables and graphs that will be visualized on the dashboard. The firm market table will be displayed in a table format and core recommendations, non-core recommendations, Sales Opportunity, Events will be visualized using doughnut charts. Again, these visualization settings can be customized based on your preferences.

# Rendering steps for the dashboard
rendering_steps = [

    # Create the global container that will encompass the entire dashboard
    config.rendering.ContainerRendering(
        label = 'Dashboard Container',
        id = 'ai2-sos-dashboard',
        query_selector = "[data-id='tabpanel-general'], [data-id='tabpanel-SUMMARY_TAB'], [class='record-page-decorator'], [data-test='fullscreen-layout']",
        height = '75',
        position = 'static',
        static_position = 'prepend'
    ),
    
    # Create the top container that will be embedded in the global container
    config.rendering.ContainerRendering(
        label = 'Top Half',
        id = 'ai2-sos-dashboard-top',
        query_selector = '#ai2-sos-dashboard',
        width = '100',
        position = 'static',
        static_position = 'append'
    ),
    
    # Create the top left container embedded in the top container
    config.rendering.ContainerRendering(
        label = 'Top Left Data Container',
        id = 'ai2-sos-dashboard-firm-score',
        query_selector = '#ai2-sos-dashboard-top',
        position = 'static',
        static_position = 'append'
    ),
    
    # Create an HTML heading in the top container
    config.rendering.HTMLTagRendering(
        label = 'Lead Name Label',
        id = 'sos-contact-name-label',
        container_id = 'ai2-sos-dashboard-firm-score',
        html_content = '<h1 id="sos-contact-name-label"></h1>',
        extra_content_tag = 'strong',
        injection_action = 'prepend',
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_value = 'Lead_Name'
    ),
    
    # Render a table of pertinent information retrieved from the ReverseML Workflow
    config.rendering.TableRendering(
        label = 'Firm Market Table',
        id = 'lead-firm-data-table',
        table_name = '',
        container_id = 'ai2-sos-dashboard-firm-score',
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_values = ['FirmName', 'AUM', 'NCF', 'Marketshare']
    ),
    
    # Render another table
    config.rendering.TableRendering(
        label = 'Engagement Trends Table',
        id = 'ai2-sos-engagment-table',
        table_name = 'Engagement Trends YTD',
        container_id = 'ai2-sos-dashboard-firm-score',
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_values = ['Web Visits', 'Marketing Emails', 'Outbound Calls', 'Inbound Calls']
    ),
    
    # Create another heading
    config.rendering.HTMLTagRendering(
        label = 'Top 3 Core Label',
        id = 'top-3-core-product-label',
        content = 'Top 3 Core Product Rx',
        container_id = 'ai2-sos-dashboard-firm-score',
        html_content = '<h1 id="top-3-core-product-label">Top 3 Core Product Rx</h1>',
        extra_content_tag = 'strong',
        injection_action = 'prepend',
        prediction_name_key = '',
        prediction_value_key = '',
        prediction_name_value = ''
    ),
    
    # Create an HTML tag for core recommendations
    config.rendering.HTMLTagRendering(
        label = 'Top Core Values',
        id = 'top-3-core-values',
        content = '',
        container_id = 'ai2-sos-dashboard-firm-score',
        html_content = '<p id="top-3-core-values"></p>',
        extra_content_tag = 'strong',
        injection_action = 'prepend',
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_value = 'Core Recommendations'
    ),
    
    # Create an HTML tag for top 3 non-core product recommendations
    config.rendering.HTMLTagRendering(
        label = 'Top 3 Non-core Label',
        id = 'top-3-non-core-product',
        content = 'Top 3 non-core Product Rx',
        container_id = 'ai2-sos-dashboard-firm-score',
        html_content = '<h1 id="top-3-non-core-product">Top 3 Non-core Product Rx</h1>',
        extra_content_tag = 'h1',
        injection_action = 'prepend',
        prediction_name_key = '',
        prediction_value_key = '',
        prediction_name_value = ''
    ),
    
    # Create and HTML tag for top 3 non-core values
    config.rendering.HTMLTagRendering(
        label = 'Top Non-Core Values',
        id = 'top-3-non-core-values',
        content = '',
        container_id = 'ai2-sos-dashboard-firm-score',
        html_content = '<p id="top-3-non-core-values"></p>',
        extra_content_tag = 'strong',
        injection_action = 'prepend',
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_value = 'Non-Core Recommendations'
    ),
    
    config.rendering.DoughnutChartRendering(
        label = 'Sales Opp Chart',
        id = 'ai2-sos-score-chart',
        chart_name = 'Sales Opp Score',
        legend_icon = 'circle',
        container_id = 'ai2-sos-dashboard-top',
        labels = None,
        labels_key = 'Lead_Name',
        consolidate_rows = True,
        prediction_name_key = 'name',
        prediction_value_key = 'value',
        prediction_name_value = 'Score',
        display_legend = True
    )
]

Feedback

For use cases where end-user feedback is solicited to help data and product teams monitor the value and accuracy of a dashboard or individual metrics within that dashboard, feedback can be easily added with AI Squared feedback components.

  • the feedback phase, the 'Simple Feedback' class as well as ‘Model Feedback’ class is chosen, which provides the ability to generate queries for user feedback.

  • This step assists in creating a feedback mechanism which enables end-users to provide essential insights on the model's performance and the output results.

model_feedback = aisquared.config.feedback.ModelFeedback('How is the propensity model performing?',
    choices = ['very poorly', 'poorly', 'neutral', 'well', 'very well'])
simple_feedback = aisquared.config.feedback.SimpleFeedback()

feedback_steps = [model_feedback, simple_feedback]

Compile Into a .air File

Now that we have all of the steps, all we have to do is put them together and compile them into a .air file to be uploaded into the platform!

# Compile all of the configuration information into a ModelConfiguration class, to
# be compiled into a .air file
model_config = config.ModelConfiguration(
    'Python SDK SOS Dashboard Multiple Applications With Doughnut Chart',
    harvesting_steps=harvester,
    preprocessing_steps=preprocesser,
    analytic=analytic,
    postprocessing_steps=postprocesser,
    rendering_steps=rendering_steps,
    feedback_steps=feedback_steps,  
    description='Version of the SOS Dashboard .air file created using the Python SDK'
)

# Compile the model
model_config.compile()

Upload the file to the platform

We are done! Now, you should have a file called Python SDK SOS Dashboard Multiple Applications in this directory. Go ahead and upload the file to the platform to start seeing results!

Last updated