How to Build a Chatbot Using Rasa: Use Case of an AI Driving Assistant

Published
Feb 17, 2022
Reading Time
Rate this post
(18 votes)
How to Build a Chatbot Using Rasa: Use Case of an AI Driving Assistant

ACF

ID81233
keyfield_631f4d7797230
labelSummary
nameblog_summary
prefixacf
typewysiwyg
value<p>A step-by-step tutorial on <strong>how to build a chatbot using Rasa</strong> (including a video explanation at the end of the article).</p> <p><b>The project partner:</b><span style="font-weight: 400;"> The use case stems from Consenz which hosted an Omdena Challenge as part of </span><a href="https://www.omdena.com/ai-program/" target="_blank" rel="noopener"><span style="font-weight: 400;">Omdena´s AI Incubator</span></a><span style="font-weight: 400;"> for impact startups.</span></p>
parent52446
wrapperArray ( [width] => [class] => [id] => )
tabsall
toolbarbasic
_nameblog_summary
_valid1

Module Settings

custom_identifierSummary
acf_namefield_631f4d7797230
is_author_acf_fieldoff
post_object_acf_namenone
author_field_typeauthor_post
linked_user_acf_namenone
type_taxonomy_acf_namenone
acf_tagspan
show_labeloff
label_seperator:
visibilityon
empty_value_optionhide_module
use_iconoff
icon_color#7EBEC5
use_circleoff
circle_color#7EBEC5
use_circle_borderoff
circle_border_color#7EBEC5
use_icon_font_sizeoff
icon_image_placementleft
image_mobile_stackinginitial
return_formatarray
image_link_urloff
image_link_url_acf_namenone
checkbox_stylearray
checkbox_radio_returnlabel
checkbox_radio_value_typeoff
checkbox_radio_linkoff
link_buttonoff
email_subjectnone
email_body_afternone
add_css_classoff
add_css_loop_layoutoff
add_css_class_selectorbody
link_new_taboff
link_name_acfoff
link_name_acf_namenone
url_link_iconoff
image_sizefull
true_false_conditionoff
true_false_condition_css_selector.et_pb_button
true_false_text_trueTrue
true_false_text_falseFalse
is_audiooff
is_videooff
video_loopon
video_autoplayon
is_oembed_videooff
defer_videooff
defer_video_iconI||divi||400
video_icon_font_sizeoff
pretify_textoff
pretify_seperator,
number_decimal.
show_value_if_zerooff
text_imageoff
is_options_pageoff
is_repeater_loop_layoutoff
linked_post_stylecustom
link_post_seperator,
link_to_post_objecton
loop_layoutnone
columns4
columns_tablet2
columns_mobile1
repeater_dyn_btn_acfnone
text_before_positionsame_line
label_positionsame_line
vertical_alignmentmiddle
admin_labelSummary
module_classsummary
_builder_version4.16
_module_presetdefault
title_css_font_size14px
title_css_letter_spacing0px
title_css_line_height1em
acf_label_css_font_size14px
acf_label_css_letter_spacing0px
acf_label_css_line_height1em
label_css_text_color#333333
label_css_font_size20px
label_css_letter_spacing0px
label_css_line_height23.5px
text_before_css_font_size14px
text_before_css_letter_spacing0px
text_before_css_line_height1em
seperator_font_size14px
seperator_letter_spacing0px
seperator_line_height1em
relational_field_item_font_size14px
relational_field_item_letter_spacing0px
relational_field_item_line_height1em
background_enable_coloroff
use_background_color_gradientoff
background_color_gradient_repeatoff
background_color_gradient_typelinear
background_color_gradient_direction180deg
background_color_gradient_direction_radialcenter
background_color_gradient_stops#2b87da 0%|#29c4a9 100%
background_color_gradient_unit%
background_color_gradient_overlays_imageoff
background_color_gradient_start#2b87da
background_color_gradient_start_position0%
background_color_gradient_end#29c4a9
background_color_gradient_end_position100%
background_enable_imageon
parallaxoff
parallax_methodon
background_sizecover
background_image_widthauto
background_image_heightauto
background_positioncenter
background_horizontal_offset0
background_vertical_offset0
background_repeatno-repeat
background_blendnormal
background_enable_video_mp4on
background_enable_video_webmon
allow_player_pauseoff
background_video_pause_outside_viewporton
background_enable_pattern_styleoff
background_pattern_stylepolka-dots
background_pattern_colorrgba(0,0,0,0.2)
background_pattern_sizeinitial
background_pattern_widthauto
background_pattern_heightauto
background_pattern_repeat_origintop_left
background_pattern_horizontal_offset0
background_pattern_vertical_offset0
background_pattern_repeatrepeat
background_pattern_blend_modenormal
background_enable_mask_styleoff
background_mask_stylelayer-blob
background_mask_color#ffffff
background_mask_aspect_ratiolandscape
background_mask_sizestretch
background_mask_widthauto
background_mask_heightauto
background_mask_positioncenter
background_mask_horizontal_offset0
background_mask_vertical_offset0
background_mask_blend_modenormal
custom_buttonoff
button_text_size20
button_bg_use_color_gradientoff
button_bg_color_gradient_repeatoff
button_bg_color_gradient_typelinear
button_bg_color_gradient_direction180deg
button_bg_color_gradient_direction_radialcenter
button_bg_color_gradient_stops#2b87da 0%|#29c4a9 100%
button_bg_color_gradient_unit%
button_bg_color_gradient_overlays_imageoff
button_bg_color_gradient_start#2b87da
button_bg_color_gradient_start_position0%
button_bg_color_gradient_end#29c4a9
button_bg_color_gradient_end_position100%
button_bg_enable_imageon
button_bg_parallaxoff
button_bg_parallax_methodon
button_bg_sizecover
button_bg_image_widthauto
button_bg_image_heightauto
button_bg_positioncenter
button_bg_horizontal_offset0
button_bg_vertical_offset0
button_bg_repeatno-repeat
button_bg_blendnormal
button_bg_enable_video_mp4on
button_bg_enable_video_webmon
button_bg_allow_player_pauseoff
button_bg_video_pause_outside_viewporton
button_use_iconon
button_icon_placementright
button_on_hoveron
positioningnone
position_origin_atop_left
position_origin_ftop_left
position_origin_rtop_left
width660px
width_tablet90%
width_phone90%
width_last_editedon|phone
max_widthnone
module_alignmentcenter
min_heightauto
heightauto
max_heightnone
custom_margin60px||60px||true|false
custom_margin_tablet50px||50px||true|false
custom_margin_phone50px||50px||true|false
custom_margin_last_editedon|phone
custom_padding24px|21px|24px|21px|true|true
filter_hue_rotate0deg
filter_saturate100%
filter_brightness100%
filter_contrast100%
filter_invert0%
filter_sepia0%
filter_opacity100%
filter_blur0px
mix_blend_modenormal
animation_stylenone
animation_directioncenter
animation_duration1000ms
animation_delay0ms
animation_intensity_slide50%
animation_intensity_zoom50%
animation_intensity_flip50%
animation_intensity_fold50%
animation_intensity_roll50%
animation_starting_opacity0%
animation_speed_curveease-in-out
animation_repeatonce
hover_transition_duration300ms
hover_transition_delay0ms
hover_transition_speed_curveease
link_option_url_new_windowoff
sticky_positionnone
sticky_offset_top0px
sticky_offset_bottom0px
sticky_limit_topnone
sticky_limit_bottomnone
sticky_offset_surroundingon
sticky_transitionon
motion_trigger_startmiddle
hover_enabled0
label_css_font_size_tablet18px
label_css_font_size_phone16px
label_css_font_size_last_editedon|desktop
label_css_line_height_tablet23.5px
label_css_line_height_phone23.5px
label_css_line_height_last_editedon|phone
title_css_text_shadow_stylenone
title_css_text_shadow_horizontal_length0em
title_css_text_shadow_vertical_length0em
title_css_text_shadow_blur_strength0em
title_css_text_shadow_colorrgba(0,0,0,0.4)
acf_label_css_text_shadow_stylenone
acf_label_css_text_shadow_horizontal_length0em
acf_label_css_text_shadow_vertical_length0em
acf_label_css_text_shadow_blur_strength0em
acf_label_css_text_shadow_colorrgba(0,0,0,0.4)
label_css_text_shadow_stylenone
label_css_text_shadow_horizontal_length0em
label_css_text_shadow_vertical_length0em
label_css_text_shadow_blur_strength0em
label_css_text_shadow_colorrgba(0,0,0,0.4)
text_before_css_text_shadow_stylenone
text_before_css_text_shadow_horizontal_length0em
text_before_css_text_shadow_vertical_length0em
text_before_css_text_shadow_blur_strength0em
text_before_css_text_shadow_colorrgba(0,0,0,0.4)
seperator_text_shadow_stylenone
seperator_text_shadow_horizontal_length0em
seperator_text_shadow_vertical_length0em
seperator_text_shadow_blur_strength0em
seperator_text_shadow_colorrgba(0,0,0,0.4)
relational_field_item_text_shadow_stylenone
relational_field_item_text_shadow_horizontal_length0em
relational_field_item_text_shadow_vertical_length0em
relational_field_item_text_shadow_blur_strength0em
relational_field_item_text_shadow_colorrgba(0,0,0,0.4)
border_radiion|6px|6px|6px|6px
border_width_all2px
border_color_all#2c39b1
button_text_shadow_stylenone
button_text_shadow_horizontal_length0em
button_text_shadow_vertical_length0em
button_text_shadow_blur_strength0em
button_text_shadow_colorrgba(0,0,0,0.4)
box_shadow_stylepreset4
box_shadow_horizontal7px
box_shadow_vertical7px
box_shadow_blur0px
box_shadow_spread0px
box_shadow_color#e0e2ff
box_shadow_positionouter
box_shadow_style_buttonnone
box_shadow_color_buttonrgba(0,0,0,0.3)
box_shadow_position_buttonouter
text_shadow_stylenone
text_shadow_horizontal_length0em
text_shadow_vertical_length0em
text_shadow_blur_strength0em
text_shadow_colorrgba(0,0,0,0.4)
disabledoff
lockedoff
global_colors_info{}

A step-by-step tutorial on how to build a chatbot using Rasa (including a video explanation at the end of the article).

The project partner: The use case stems from Consenz which hosted an Omdena Challenge as part of Omdena´s AI Incubator for impact startups.

Execution time: 0.0015 seconds

ACF

ID52447
keyfield_61fcd4e1daf53
labelJump to Section
nameblog_jum_to_section
prefixacf
typewysiwyg
value<ul> <li><a href="#introduction"><span style="font-weight: 400;">Introduction</span></a></li> <li><a href="#key-chatbot-concepts"><span style="font-weight: 400;">Key chatbot concepts</span></a></li> <li><a href="#how-do-you-develop-a-chatbot"><span style="font-weight: 400;">How do you develop a chatbot?</span></a></li> <li><a href="#choice-of-a-chatbot-tool"><span style="font-weight: 400;">Choice of a chatbot tool</span></a></li> <li><a href="#creating-a-rasa-bot"><span style="font-weight: 400;">Creating a Rasa bot</span></a></li> <li><a href="#conclusions"><span style="font-weight: 400;">Conclusions</span></a></li> </ul>
menu_order1
parent52446
wrapperArray ( [width] => [class] => [id] => )
tabsall
toolbarbasic
_nameblog_jum_to_section
_valid1

Module Settings

custom_identifierJump to section
acf_namefield_61fcd4e1daf53
is_author_acf_fieldoff
post_object_acf_namenone
author_field_typeauthor_post
linked_user_acf_namenone
type_taxonomy_acf_namenone
acf_tagdiv
show_labelon
label_seperator
custom_labelJump to section
visibilityon
empty_value_optionhide_module
use_iconoff
icon_color#7EBEC5
use_circleoff
circle_color#7EBEC5
use_circle_borderoff
circle_border_color#7EBEC5
use_icon_font_sizeoff
icon_image_placementleft
image_mobile_stackinginitial
return_formatarray
image_link_urloff
image_link_url_acf_namenone
checkbox_stylearray
checkbox_radio_returnlabel
checkbox_radio_value_typeoff
checkbox_radio_linkoff
link_buttonoff
email_subjectnone
email_body_afternone
add_css_classoff
add_css_loop_layoutoff
add_css_class_selectorbody
link_new_tabon
link_name_acfoff
link_name_acf_namenone
url_link_iconoff
image_sizefull
true_false_conditionoff
true_false_condition_css_selector.et_pb_button
true_false_text_trueTrue
true_false_text_falseFalse
is_audiooff
is_videooff
video_loopon
video_autoplayon
is_oembed_videooff
defer_videooff
defer_video_iconI||divi||400
video_icon_font_sizeoff
pretify_textoff
pretify_seperator,
number_decimal.
show_value_if_zerooff
text_imageoff
is_options_pageoff
is_repeater_loop_layoutoff
linked_post_stylecustom
link_post_seperator,
link_to_post_objecton
loop_layoutnone
columns4
columns_tablet2
columns_mobile1
repeater_dyn_btn_acfnone
text_before_positionsame_line
label_positionsame_line
vertical_alignmentmiddle
admin_labelTable of contents
module_classblog-table-of-contents
_builder_version4.16
_module_presetdefault
title_css_font_size14px
title_css_letter_spacing0px
title_css_line_height1em
acf_label_css_font|600|||||||
acf_label_css_text_color#2c38b1
acf_label_css_font_size28px
acf_label_css_letter_spacing0px
acf_label_css_line_height1em
label_css_font_size16px
label_css_letter_spacing0px
text_before_css_font_size14px
text_before_css_letter_spacing0px
text_before_css_line_height1em
seperator_font_size14px
seperator_letter_spacing0px
seperator_line_height1em
relational_field_item_font_size14px
relational_field_item_letter_spacing0px
relational_field_item_line_height1em
background_color#f7f7f7
background_enable_coloron
use_background_color_gradientoff
background_color_gradient_repeatoff
background_color_gradient_typelinear
background_color_gradient_direction180deg
background_color_gradient_direction_radialcenter
background_color_gradient_stops#2b87da 0%|#29c4a9 100%
background_color_gradient_unit%
background_color_gradient_overlays_imageoff
background_color_gradient_start#2b87da
background_color_gradient_start_position0%
background_color_gradient_end#29c4a9
background_color_gradient_end_position100%
background_enable_imageon
parallaxoff
parallax_methodon
background_sizecover
background_image_widthauto
background_image_heightauto
background_positioncenter
background_horizontal_offset0
background_vertical_offset0
background_repeatno-repeat
background_blendnormal
background_enable_video_mp4on
background_enable_video_webmon
allow_player_pauseoff
background_video_pause_outside_viewporton
background_enable_pattern_styleoff
background_pattern_stylepolka-dots
background_pattern_colorrgba(0,0,0,0.2)
background_pattern_sizeinitial
background_pattern_widthauto
background_pattern_heightauto
background_pattern_repeat_origintop_left
background_pattern_horizontal_offset0
background_pattern_vertical_offset0
background_pattern_repeatrepeat
background_pattern_blend_modenormal
background_enable_mask_styleoff
background_mask_stylelayer-blob
background_mask_color#ffffff
background_mask_aspect_ratiolandscape
background_mask_sizestretch
background_mask_widthauto
background_mask_heightauto
background_mask_positioncenter
background_mask_horizontal_offset0
background_mask_vertical_offset0
background_mask_blend_modenormal
custom_buttonoff
button_text_size20
button_bg_use_color_gradientoff
button_bg_color_gradient_repeatoff
button_bg_color_gradient_typelinear
button_bg_color_gradient_direction180deg
button_bg_color_gradient_direction_radialcenter
button_bg_color_gradient_stops#2b87da 0%|#29c4a9 100%
button_bg_color_gradient_unit%
button_bg_color_gradient_overlays_imageoff
button_bg_color_gradient_start#2b87da
button_bg_color_gradient_start_position0%
button_bg_color_gradient_end#29c4a9
button_bg_color_gradient_end_position100%
button_bg_enable_imageon
button_bg_parallaxoff
button_bg_parallax_methodon
button_bg_sizecover
button_bg_image_widthauto
button_bg_image_heightauto
button_bg_positioncenter
button_bg_horizontal_offset0
button_bg_vertical_offset0
button_bg_repeatno-repeat
button_bg_blendnormal
button_bg_enable_video_mp4on
button_bg_enable_video_webmon
button_bg_allow_player_pauseoff
button_bg_video_pause_outside_viewporton
button_use_iconon
button_icon_placementright
button_on_hoveron
positioningnone
position_origin_atop_left
position_origin_ftop_left
position_origin_rtop_left
widthauto
max_widthnone
min_heightauto
heightauto
max_heightnone
custom_margin50px||50px||true|false
custom_padding30px|20px|30px|20px|true|true
filter_hue_rotate0deg
filter_saturate100%
filter_brightness100%
filter_contrast100%
filter_invert0%
filter_sepia0%
filter_opacity100%
filter_blur0px
mix_blend_modenormal
animation_stylenone
animation_directioncenter
animation_duration1000ms
animation_delay0ms
animation_intensity_slide50%
animation_intensity_zoom50%
animation_intensity_flip50%
animation_intensity_fold50%
animation_intensity_roll50%
animation_starting_opacity0%
animation_speed_curveease-in-out
animation_repeatonce
hover_transition_duration300ms
hover_transition_delay0ms
hover_transition_speed_curveease
link_option_url_new_windowoff
sticky_positionnone
sticky_offset_top0px
sticky_offset_bottom0px
sticky_limit_topnone
sticky_limit_bottomnone
sticky_offset_surroundingon
sticky_transitionon
motion_trigger_startmiddle
hover_enabled0
acf_label_css_font_size_tablet24px
acf_label_css_font_size_phone22px
acf_label_css_font_size_last_editedon|phone
title_css_text_shadow_stylenone
title_css_text_shadow_horizontal_length0em
title_css_text_shadow_vertical_length0em
title_css_text_shadow_blur_strength0em
title_css_text_shadow_colorrgba(0,0,0,0.4)
acf_label_css_text_shadow_stylenone
acf_label_css_text_shadow_horizontal_length0em
acf_label_css_text_shadow_vertical_length0em
acf_label_css_text_shadow_blur_strength0em
acf_label_css_text_shadow_colorrgba(0,0,0,0.4)
label_css_text_shadow_stylenone
label_css_text_shadow_horizontal_length0em
label_css_text_shadow_vertical_length0em
label_css_text_shadow_blur_strength0em
label_css_text_shadow_colorrgba(0,0,0,0.4)
text_before_css_text_shadow_stylenone
text_before_css_text_shadow_horizontal_length0em
text_before_css_text_shadow_vertical_length0em
text_before_css_text_shadow_blur_strength0em
text_before_css_text_shadow_colorrgba(0,0,0,0.4)
seperator_text_shadow_stylenone
seperator_text_shadow_horizontal_length0em
seperator_text_shadow_vertical_length0em
seperator_text_shadow_blur_strength0em
seperator_text_shadow_colorrgba(0,0,0,0.4)
relational_field_item_text_shadow_stylenone
relational_field_item_text_shadow_horizontal_length0em
relational_field_item_text_shadow_vertical_length0em
relational_field_item_text_shadow_blur_strength0em
relational_field_item_text_shadow_colorrgba(0,0,0,0.4)
border_radiion|5px|5px|5px|5px
button_text_shadow_stylenone
button_text_shadow_horizontal_length0em
button_text_shadow_vertical_length0em
button_text_shadow_blur_strength0em
button_text_shadow_colorrgba(0,0,0,0.4)
box_shadow_stylenone
box_shadow_colorrgba(0,0,0,0.3)
box_shadow_positionouter
box_shadow_style_buttonnone
box_shadow_color_buttonrgba(0,0,0,0.3)
box_shadow_position_buttonouter
text_shadow_stylenone
text_shadow_horizontal_length0em
text_shadow_vertical_length0em
text_shadow_blur_strength0em
text_shadow_colorrgba(0,0,0,0.4)
disabledoff
global_colors_info{}

Execution time: 0.0011 seconds

Authors: Anna Koroleva, Simon Mackenzie, Saheen Ahamed

Introduction

Chatbots, or conversational agents, have become very popular in the past years. We come across them constantly in our everyday life, often without even noticing (remember the chat box in the app of your bank, mobile provider, or on your favorite online shopping website?).

Source: https://www.societegenerale.com/en 

Source: https://www.societegenerale.com/en

Chatbots are there to help us with many tasks, such as setting up alarms, scheduling meetings, or finding an answer to our question on a company website. Why are chatbots important? They step in when there’s not enough human assistants to handle all the requests, thus making the assistance available for a large number of users.

Chatbots use technology such as Natural Language Understanding (NLU) and Machine Learning (ML) to understand users’ requests, produce adequate responses, and perform correct actions. Chatbot development is an exciting and fast-growing domain of ML, with a lot of open- or closed-source tools, courses, and tutorials available to help you build your own chatbot.

That’s exactly what we set out to do in a recent AI challenge organized by Omdena and Consenz: build a chatbot to be the core of Enzo – a hands-free driving assistant, whose main goal is reducing the number of traffic accidents. To that end, the chatbot should be able to understand the driver’s commands regarding navigation, music, calls, etc, and respond to them adequately.

We have all heard about chatbots and all were interested in developing one ourselves. We were aware of tools such as Dialogflow or Rasa and had previously followed some courses or tutorials on chatbot development. We were eager to apply in practice what we had learnt.

However, even with all available resources, it turned out not to be so easy to get started with building a chatbot. The abundance of information makes it hard to find a good starting point, and many technical details and features are tricky to master and can be confusing for a beginner. In our development process, we were learning a lot every day and had a lot of “I wish I’d known this before!” moments. That’s why we decided to write this article – not intending to repeat any courses or tutorials, but willing to share our experience and learnings to help others get started in chatbot development easier.

Read on to learn about the key concepts of chatbot development, an overview of the development, our thoughts regarding the choice of a chatbot tool, an introduction to Rasa conversational agents (with code snippets and examples of data and configurations), and a hands-on session allowing you to get started with creating a chatbot quickly.

Build your portfolio with real-world projects from Omdena

Key chatbot concepts

Before we dive into the details of how we were building our driver’s assistant agent, it’s useful to define the key concepts of chatbot development:

  • Utterance is anything the user says to the bot, for example, “Get me to 221b Baker St”, “Drive from my current location to Sherlock Holmes museum avoiding the center of the city”, “Start navigation”.
  • Intent is the user’s goal when they are saying an utterance, for example in the examples above, the user wants to be navigated to a place, and we could call the intent “navigate_to”.
  • Entities can be seen as “parameters” of an intent, making it specific and allowing to understand the exact action the user wants to be performed. Entities typically have types assigned to them. In the examples above, “221b Baker St”, ”my current location”,  “Sherlock Holmes museum” and “the center of the city” are all entities. Their types could be “destination” for 221b Baker St” and “Sherlock Holmes museum”; “origin” for ”my current location”; and “avoid_point” for “the center of the city”.
  • Response is anything the bot says in reaction to the user’s utterances, e.g. “you are welcome” in response to “thank you”.
  • Action is something that the bot needs to do to adequately fulfill the goal of the user. For many intents, a simple response is not enough: the bot should not just say “starting navigation” in response to “navigate_to” intent, it should also memorise the destination, origin, points to be included or avoided, and actually connect to a maps API, calculate the route according to the given parameters, and start navigating.
  • Conversation flow is the way a conversation develops over a few conversational turns. We want the interaction of the user and the chatbot to be smooth and natural, which would indicate that we designed the conversation flow well.

The scheme below shows an example of steps involved in a user/bot interaction:

Fig. 1. An example scheme of bot-user interaction

Fig. 1. An example scheme of bot-user interaction

How do you develop a chatbot?

One reason why developing a chatbot is a heavy task for a beginner is that it consists of two large, equally complex components. 

First, there is the conversation design part, which includes answering the following questions:

  • What is the user expected to say/request?
  • Which variants of a request are the same request and which should be treated differently?
  • How is the bot expected to reply and act?
  • What are the possible ways a conversation can go?

and more. This part is largely independent of the chatbot tool. Working on the conversation design of your bot is an iterative process: there will always be some unexpected requests or turns or conversation when your users are interacting with the bot. So, you start with it, but don’t expect to finish the conversation design of your bot before you proceed.

Second there is implementation which deals with the following questions:

  • How do we formalise the behaviour we want?
  • What data do we need, in which formats? How do we obtain the data?
  • Which packages do we need?
  • Which model do we train?
  • How do we test?
  • What code do we need to write?

This part depends on the tool you choose, and will also impact the conversation design as you identify wrong conversation during testing.

Choice of a chatbot tool

There are many tools for chatbot development: Google’s Dialogflow, Amazon Lex, Mycroft, Rasa, and more. All tools have their own advantages and disadvantages with regards to being open- or closed-source, price, necessity (or absence thereof) to write any code, complexity of installation and getting started, and so on.

No one would like to realise that the tool they have been using for months does not have the desired functionality, so we all want to get it right from the beginning. But when you are just starting your chatbot journey and still defining what exactly you want from your bot, it can be daunting to define which tool would suit your needs best. After a good deal of research, we chose Rasa because:

  • its core component is open-source and free
  • it allows to incorporate many external state-of-the-art NLP models
  • it is highly customizable and flexible (more on that later)
  • it uses Python which is our language of choice
  • It has an easy-to-use command-line interface for common tasks such as training, testing or running models
  • it has great documentation, written and video tutorials (check out “Conversational AI with Rasa” series on Youtube).

Creating a Rasa bot

Installing Rasa

Rasa Open Source packages are available in Python Package Index Repository (PyPI). The default installation can be performed by using pip install rasa command and it requires python version >=3.7, <3.9. But some of the most useful functionality, such as the most state-of-the-art transformer-based NLP models, are not included in the default installation, so we’d recommend using pip install rasa[full] instead.

Rasa models

It’s very important to understand that Rasa agents consist of two models: an NLU model and a core model. The NLU model is responsible for recognising the intents of the user’s utterances and for extracting the entities present in them. The core model is responsible for managing the conversation flow: memorising the entities, producing the correct response and/or action, understanding when it’s time to wait for the next user’s utterance, and so on. The two models are trained on different data. It is possible to train NLU and core models separately with Rasa, but to get a complete agent capable of interacting with a user, we need to have both components.

Although the core model decides what is the correct action to perform, it does not actually perform it. There is a separate action server that is in charge of running actions. 

Fig.2. Structure of a Rasa bot

Fig.2. Structure of a Rasa bot

Creating a project

To train a Rasa model, we need the data for the NLU component, for the core component, and also we need to define responses and actions the bot is expected to perform. Hence, the file structure needed to train a Rasa bot is quite complex. But luckily, you do not need to set it up manually, you can run rasa init in a terminal to create your first project. Although you would get the correct folder structure, there are a lot of sub-folders and files, and figuring out what to do next can be overwhelming. So let’s take a closer look at what’s in there.

What does a Rasa bot consist of?

The folder structure of our newly created agent is as follows:

Fig.3. Folder structure of a Rasa project

Fig.3. Folder structure of a Rasa project

You’d typically start creating a bot from some amount of NLU training data, then core data and actions. But we are going to talk about actions first because we’ll need some concepts for explaining training data later on.

Custom actions

actions.py file defines custom actions that a bot can perform in reply to user’s commands. This is one of Rasa’s most powerful customisation capabilities: you can really do a lot with custom actions.

Two key components used in actions are the dispatcher, which can generate responses, and the tracker which stores the bot’s memory. The bot’s memory contains the information about what the user said: text of utterances, intents, entities. A separate part of Rasa bot’s memory are slots – variables where you can store important information. Slots can be of various types such as string, list, bool, etc. You don’t always need custom actions to work with slots: in Rasa 2.x, a slot is filled automatically with an entity of the same name (in Rasa 3.x, you need to specify which entity should fill which slot), e.g. a “destination” slot will be filled when a “destination” entity is extracted from the input utterance. However, in some cases, you might want to fill slots in a different way. In this case, you can use slot names that differ from entity names, and fill them through actions.

For example, when a user gives the bot a destination, we might want to check whether the “main_destination” slot is already filled: if it is, we add the new destination to the “include-point” list, instead of rewriting the main destination:

class ActionAddDestinaton(Action):
    def name(self) -> Text:
        return "action_add_destination"
    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
        entity_to = next(tracker.get_latest_entity_values(entity_type="location", entity_role="to"), None)
        slot_main_destination = tracker.get_slot('main_destination')
        slot_include_point = tracker.get_slot('include-point')
        if slot_main_destination is None:
            return [SlotSet("main_destination", entity_to)]
        else:
         if slot_include_point is not None:
             slot_include_point.append(entity_include_point)
else:
slot_include_point = [entity_include_point]
            return [SlotSet("include-point", entity_to)]

A few points to note: 

  • We would use  return [SlotSet("main_destination", entity_to), SlotSet("include-point", slot_include_point ), …] to fill several slots at a time.
  • To add a new item to a list slot (include-point), we first read the slot value by slot_include_point = tracker.get_slot('include-point'), then append items to slot_include_point, and then running return [SlotSet("include-point", entity_to)].
  • name() function defines the name we use to refer to the action in core training data (action_add_destination in this example).

Another cool feature that can be implemented using custom actions is using a database to store user-specific information, e.g. a home address. We can write an action saving items to a database:

class ActionAddToDatabase(Action):
    def name(self) -> Text:
        return "action_add_to_database"
    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
        entity_location = next(tracker.get_latest_entity_values(entity_type="location"), None)
        entity_db_item_name = next(
            tracker.get_latest_entity_values(entity_type="location", entity_role="to_database"), None)
        with open('utils/database.json', 'r', encoding = 'utf-8') as db:
            database = json.load(db)
        database.update({entity_db_item_name: entity_location})
        with open('utils/database.json', 'w', encoding = 'utf-8') as db:
            json.dump(database, db)
        return []

When a user triggers the corresponding intent, database files gets updated:

Source: Omdena

Source: Omdena

After that, we just need to add a few more lines to our ActionAddDestinaton to read that information back:

        with open('utils/database.json', 'r', encoding = 'utf-8') as db:
            database = json.load(db)
        if entity_to in database:
            entity_to = database[entity_to]

The user can now ask to go home, instead of providing the full address each time:

Source: Omdena

Source: Omdena

We can further use a database to store the user’s navigation history, e.g:

database = {
    "destinations": [
        ["5 main street", "17.50 23.11.21"],
        ["12 royal court drive", "17.45 16.11.21"],
        ["12 royal court drive", "17.51 09.11.21"],
        ["5 main street", "17.48 02.11.21"],
        ["5 main street", "17.49 26.10.21"],
    ]
}

We can notice that our user tends to drive to the same places at similar times. If he triggers the navigate_to intent at one of those times without giving a destination, it would make sense to suggest the place where he usually goes at this time. We add a function to do this:

def get_frequent_destination(
   database, weeks_limit=5, weekly_events_min_count=3, daily_events_min_count=10
):
   time_now = datetime.now()
   weekday_now = time_now.weekday()
   hour_now = time_now.hour
   time_limit = time_now - timedelta(weeks=weeks_limit)
   time_limit = time_limit
   destinations_by_day_and_time = Counter()
   destinations_by_time = Counter()
   if "destinations" in database:
       for destination in database["destinations"]:
           address, trip_date = destination
           address = address.lower()
           trip_date = datetime.strptime(trip_date, date_string_pattern)
           weekday = trip_date.weekday()
           hour = trip_date.hour
           if trip_date >= time_limit:
               if weekday == weekday_now and hour == hour_now:
                   destinations_by_day_and_time[address] += 1
               if hour == hour_now:
                   destinations_by_time[address] += 1
   if len(destinations_by_day_and_time) > 0 or len(destinations_by_time) > 0:
       top_destination, count = destinations_by_day_and_time.most_common(1)[0]
       if count >= weekly_events_min_count:
           return top_destination
       else:
           top_destination, count = destinations_by_time.most_common(1)[0]
           if count >= daily_events_min_count:
               return top_destination
   return

Now we see the following behaviour – just what we wanted:

Source: Omdena

Source: Omdena

Finally, one more fun feature we created using actions and slots is customising the bot’s response to some parameters of the user that are calculated based on his previous utterance(s). A very simple implementation of this feature is to store average length of every intent, mark the user as “talkative” if his/her utterance is longer than average, “not talkative” otherwise, and return a longer/shorter response accordingly. We take entities’ lengths to be 1: “Drive to 221B Baker Street” and “Drive to London” should be considered the same length. We use a custom action to access the text of the last user’s message, entities in it, do some length calculations (tokenising simply by white space), and fill the is_talkative slot:

class ActionSetUserFeats(Action):
    def name(self) -> Text:
        return "action_set_user_feats"
    def run(self, dispatcher: CollectingDispatcher,
            tracker: Tracker,
            domain: Dict[Text, Any]) -> List[Dict[Text, Any]]:
        user_message = tracker.latest_message['text']
        entities = tracker.latest_message['entities']
        entity_length = sum([len(e['value'].split()) for e in entities])
        intent = tracker.latest_message['intent'].get('name')
        l = len(user_message.split()) - entity_length + len(entities) # count each entity as one word
        if l > avg_lengths[intent]:
            is_talkative = True
        else:
            is_talkative = False
        return [SlotSet("is_talkative", is_talkative)]

To choose a longer response if the user is talkative, and a default response otherwise, we use a conditional response (responses are specified in domain.yml – see below):

  utter_navigation_started:
  - condition:
    - type: slot
      name: is_talkative
      value: true
    text: Hey, sure. Starting navigation from {from} to {main_destination}
  - text: Navigating from {from} to {main_destination}

Now the bot will reply differently depending on the user’s input:

Source: Omdena

Source: Omdena

Now you know how to write custom actions, but one thing is missing: how does the bot know which actions to perform? Read on to the next sessions to learn that!

Training data

Data folder contains data for both NLU and core model training.

NLU training data

The data for training the NLU model is contained in nlu.yml. Its main part is intent names and examples of intent sentences with annotated entities:

- intent: Navigate
  examples: |
    - navigate me to [london](to)
- navigate to [Barrgatan 7](to) from [Moskosel](from)
- navigate to [Birmingham](to) from [London](from)

Note: entity text is enclosed in square brackets, and entity type in parentheses.

After testing, we realised that “to” and “from” entity types often get mixed up: e.g. in “Navigate from Birmingham to London”, both cities would be recognised as the entity type “to”. It makes sense: without context, entities “Birmingham” and “London” are very similar. Entity type “to” is much more frequent in navigation than entity type “from”, which would typically be assumed to be the user’s current location. Hence, “to” is predicted more frequently. Rasa has a solution for this problem: we can assign the same type, but different roles, to the origin and destination, which resolves the issue:

- intent: Navigate
  examples: |
    - navigate me to [london]{"entity": "location", "role": "to"}
- navigate to [Barrgatan 7]{"entity": "location", "role": "to"} from [Moskosel]{"entity": "location", "role": "from"}
- navigate to [Birmingham]{"entity": "location", "role": "to"} from [London]{"entity": "location", "role": "from"}

Some more options for extracting entities include:

  • synonyms: variants of an entity that would all be mapped to a standard variant. In the navigation bot, we had an intent that would save an address to a database, and we’d like the versions like “My address is 6 London drive”, “Save 6 London drive as home”, “I live at  6 London drive”, etc. to be all saved under “home”. Hence we used a synonym mapping:
- synonym: home
  examples: |
    - I live at
    - my home address
    - my address
    - my home

Note that you do not need to include the standard variant (‘home) in the synonyms list, it only needs to be mentioned at the first line: – synonym: home. Also note that all variants need to be present in the training examples for intents. Finally, make sure to include the following into your config.yml (more about the config file later):

- name: EntitySynonymMapper
  • regular expressions: you can define a regex that will be used for rule-based entity extraction:
- intent: call_number
  examples: |
    - call [07869613248](phone_number)
    - dial [7869613248](phone_number)
- regex: account_number
  examples: |
    - \d{10,12}
  • Lookup tables: you can define a list of words and phrases belonging to an entity:
- lookup: city
  examples: |
    - London
    - Birmingham
    - ...

Note that this would only work well if an entity contains a closed list of words. Otherwise you need to train an NER (Named Entity Recognition) model or use an existing one (see Configuration section).

To use regexes and lookup tables,you need to add RegexEntityExtractor and RegexFeaturizer to your config.yml.

Core training data

Core training data is vital for the core component of a Rasa model – the one that handles the conversation flow. A core model consists of rules and an ML model. The data is stored in rules.yml and stories.yml, correspondingly.

Rules define short dialogue fragments that are fixed: typically it is one intent and a response and/or action that should always follow that intent. For example, if the user asks what the bot can do (what_scope intent), the bot always explains the scope of its capabilities (utter_scope response):

- rule: what_scope
  steps:
  - intent: what_scope
  - action: utter_scope

Stories are used to train the ML part of the core model. They describe longer, more complex dialogue fragments that will help the bot to learn how to handle more varied conversations and generalise to unseen data.

We described above the action_set_user_feats action that compares the length of the user’s input to the average length of the corresponding intent and sets is_talkative slot. We defined a conditional response utter_navigation_started that would return a longer reply if is_talkative slot is set to True. To teach the bot to run this action after the user triggers the navigate_to intent and before returning the utter_navigation_started response, we write the following story:

- story: Navigate
  steps:
    - intent: navigate_to
      entities:
      - location: "221B Baker street London"
        role: to
    - action: action_add_destination
    - slot_was_set:
      - main_destination: "221B Baker street London"
    - action: action_set_user_feats
    - slot_was_set:
      - is_talkative: true
    - action: action_start_navigation
    - action: utter_navigation_started
    - action: action_listen

Note that, unlike rules, in stories we provide examples of entities and reflect slot filling.

If the user triggers navigate_to intent but does not provide a destination, the main_destination slot would not be filled after the first message. The bot would need to additionally ask the user to provide a destination. This scenario needs to be described by a separate story:

- story: Open_gps
  steps:
    - intent: navigate_to
      entities:
      - location: null
    - action: action_add_destination
    - slot_was_set:
      - main_destination: null
    - action: action_set_user_feats
    - slot_was_set:
      - is_talkative: true
    - action: utter_ask_for_destination
    - action: action_listen
    - intent: navigate_to
      entities:
      - location: "221B Baker street London"
        role: to
    - action: action_add_destination
    - slot_was_set:
      - main_destination: "221B Baker street London"
    - action: action_start_navigation
    - action: utter_navigation_started
    - action: action_listen

In this case, the value of the main_destination slot (None vs filled) impacts the conversation. When we are specifying slots in the domain file (see below), we need to set the influence_conversation flag to True for this kind of slots.

Creating stories manually can be a pain, particularly when you are just getting familiar with Rasa. An extremely useful tool for creating stories (and better understanding them) is the command line rasa interactive option: it launches an interactive interface where you can type messages as a user, check whether the intent and entities are recognised correctly, fix them if not, track the slot filling, check and correct the next action:

Fig.4. An example of Rasa interactive interface

Fig.4. An example of Rasa interactive interface

Be careful: rasa interactive will retrain your models every time you launch it if the data has changed! Using rasa interactive to write just one story is not time-efficient, it’s best to create several stories at a time and retrain after that. To start a new story, run /restart in rasa interactive.

As conversation flow management in Rasa is mainly ML-based, its behaviour can change every time you add new data and retrain your model. It means that something that used to work perfectly can stop working at some iteration. What does this mean? We need testing! Luckily, Rasa provides possibilities for automated testing using test stories. They are very similar to the training stories, except for the need to spell out the whole user’s input (instead of just entities):

- story: Navigate to location
  steps:
  - user: |
      hello
    intent: hello
  - action: utter_hello
  - user: |
     navigate to [7 Victor Hugo drive]{"entity": "location", "role": "to"} please
    intent: navigate_to
  - action: action_add_destination
  - slot_was_set:
    - main_Destination: 7 Victor Hugo drive
  - action: action_set_user_feats
  - slot_was_set:
    - is_talkative: false
  - action: action_start_navigation
  - action: utter_navigation_started

To run the test, use rasa test in the command line.

Domain

Finally, the domain file lists all the information about training data and actions: intents, entities, slots with their types, default values and influence_conversation flag, forms, actions:

version: '2.0'
session_config:
  session_expiration_time: 60
  carry_over_slots_to_new_session: true
intents:
- ...
entities:
- ...
slots:
  <slot name>:
    type: text
    influence_conversation: true
  <slot name>:
    type: list
    influence_conversation: false
responses:
  utter_<response name>:
  - text: ...
actions:
- action_<action name>

Forms in Rasa provide a way to collect some required information from the user, for example the destination for “navigate_to”intent”. Forms are defined in the domain file as follows:

forms:
  navigate_form:
    required_slots:
        - main_destination

You can use the forms in stories and rules by referring to the form’s name (navigate_form in our example):

- rule: Activate form
  steps:
  - intent: navigate_to
  - action: navigate_form
  - active_loop: navigate_form

active_loop states that the form should be activated at this point of the dialogue. The form gets deactivated automatically when all required slots are filled.

Configuration

Now it’s time to look at the configuration file used for training models: config.yml. It includes two parts: configuration for the NLU model and configuration for the core model. As we have already mentioned, Rasa models are highly customisable, and we can see it now: you can choose between a number of pre-processing options, featurisers, ML models for intent classification and named entity recognition (NER). Pre-trained NER models from spacy and Duckling are available. You can use classic ML or state-of-the-art deep learning models, including transformers (Rasa’s DIETClassifier). Look-up dictionaries and regular expressions can also be used for NER. The full list of pipeline components can be found at https://rasa.com/docs/rasa/components/.

It’s good to remember that, though transformers are incredibly powerful, training a transformer model takes a while, and you need to have a decent amount of data to get the desired results. It is worth trying out spacy and/or Duckling NER models before training your own: they might already have all you need.

In the case of our navigation bot, we needed a module for address extraction. Spacy recognises locations such as cities and countries, but not full addresses such as “221B Baker street London”, so we had to collect some examples of addresses and train our own NER model. We started with the following config.yml that showed a good performance:

 

# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: "en"
pipeline:
- name: "HFTransformersNLP"
  model_weights: "distilbert-base-uncased"
  model_name: "distilbert"
- name: "LanguageModelTokenizer"
- name: "LanguageModelFeaturizer"
- name: "DIETClassifier"
  random_seed: 42
  intent_classification: True
  entity_recognition: True
  use_masked_language_model: True
  epochs: 5
  number_of_transformer_layers: 4
  transformer_size: 256
  drop_rate: 0.2
  batch_size: 32
  embedding_dimension: 50
# other components
- name: FallbackClassifier
  threshold: 0.5
- name: EntitySynonymMapper
configuration for the NLU model
Policies:
# # See https://rasa.com/docs/rasa/policies for more information.
   - name: MemoizationPolicy
   - name: RulePolicy
   - name: UnexpecTEDIntentPolicy
     max_history: 5
     epochs: 100
   - name: TEDPolicy
     max_history: 5
     epochs: 100
     constrain_similarities: true
configuration for the core model

Table. 1. Example of config.yml

Note that you can run into memory issues while training a transformer. We found that experimenting with the following parameters: number_of_transformer_layers, transformer_size, batch_size, embedding_dimension can help solve the problem.

After we started adding intents for calling/messaging, we realised we needed entities such as names and phone numbers. Names can be very diverse, and phone numbers in different countries follow different patterns (and we can never be sure of the exact formatting we get as the input), so it proved more reasonable to use spacy’s PERSON entity and a few Duckling’s entity including distance, duration, and phone-number. To incorporate these models, we changed the NLU configuration as follows (note how we add our own preprocessor):

# Configuration for Rasa NLU.
# https://rasa.com/docs/rasa/nlu/components/
language: en
pipeline:
- name: ourpreprocessor.OurPreprocessor
# language model
- name: WhitespaceTokenizer
- name: LanguageModelFeaturizer
  model_weights: distilbert-base-uncased
  model_name: distilbert
# Regex for phone numbers
- name: RegexFeaturizer
# dual intent and entity
- name: DIETClassifier
  random_seed: 42
  batch_size: 32
  intent_classification: True
  entity_recognition: True
  use_masked_language_model: False
  constrain_similarities: True
  epochs: 35
  evaluate_on_number_of_examples: 200
  evaluate_every_number_of_epochs: 1
  tensorboard_log_directory: "./tbdiet"
  tensorboard_log_level: "epoch"
# pretrained spacy NER for PERSON
- name: SpacyNLP
  model: en_core_web_md
- name: SpacyEntityExtractor
  dimensions: [PERSON]
- name: DucklingEntityExtractor
  url: "http://localhost:8000"
  locale: "en_GB"
  timezone: "UTC"
  dimensions: [distance, duration, number, ordinal, phone-number, time, temperature]
# other components
- name: FallbackClassifier
  threshold: 0.4
- name: EntitySynonymMapper

An important part of the configuration is handling of fallbacks which can be of two types:

  • NLU fallback: the bot does not reliably recognise the user’s intent. This happens when the confidence of predicted intents is below the threshold set by:
- name: FallbackClassifier
  threshold: 0.4

In this case, by default, action_default_fallback will be performed, sending utter_default to the user. But we did not want our bot to keep repeating the same default fallback response in case it does not understand the user repeatedly – that’s quite unnatural. We wanted to have several options of the reprompt that would be selected randomly every time, making sure that they do not repeat. We achieved this by writing a custom action:

class ActionReprompt(Action):
    """Executes the fallback action and goes back to the previous state
    of the dialogue"""
    def name(self) -> Text:
        return 'action_reprompt'
    async def run(
        self,
        dispatcher: CollectingDispatcher,
        tracker: Tracker,
        domain: Dict[Text, Any],
    ) -> List[Dict[Text, Any]]:
        reprompts = ["I'm sorry, I didn't quite understand that. Could you rephrase?",
                     "Sorry, I didn't catch that, can you rephrase?",
                     "Apologies, I didn't understand. Could you please rephrase it?"]
        last_reprompt = tracker.get_slot('last_reprompt')
        if last_reprompt in reprompts:
            reprompts.remove(last_reprompt)
        reprompt = random.choice(reprompts)        
        dispatcher.utter_message(text=reprompt)
        return [SlotSet("last_reprompt", reprompt)]

To use this action instead of the default one, we introduce a new rule:

- rule: Implementation of Fallback
  steps:
  - intent: nlu_fallback
  - action: action_reprompt

  • Core fallback: the bot can not reliably predict the next action. action_default_fallback will be performed by default. Threshold for this fallback is set in the core model configuration:
 - name: "RulePolicy"
    core_fallback_threshold: 0.3
    core_fallback_action_name: action_default_fallback
    enable_fallback_prediction: true
    restrict_rules: true
    check_for_contradictions: true

How to train and run Rasa models?

You can train and run models locally via command line:

  • rasa train to train an NLU and core model
  • rasa train nlu to train an NLU model
  • rasa train core to train a core model

To launch your Rasa agent in the command line, use rasa shell. If you have custom actions, you need to launch rasa run actions in a separate terminal window first to start the Rasa action server (keep it open while running rasa shell).

Hands-on: your first agent

That was a long read! You see now why it’s hard to get started with Rasa?

There is a little trick that can be used as a first learning project with Rasa: use an existing chatbot from the list of Dialogflow pre-built agents (under the ‘Pre-built agents’ tab in the left sidebar menu) and convert it to Rasa. This allows you to get familiar with the development process without thinking of the conversational design part too much. You can create a free Dialogflow account, create a new agent, and import one of pre-built agents into your agent. Then, going to the Settings, you can export a ZIP archive with the agent’s data:

Fig 5. Exporting ZIP archive

Fig 5. Exporting ZIP archive

Unzip the downloaded archive to a directory. Create a new folder where you want to create your Rasa bot. To convert Dialogflow NLU data to Rasa NLU data, use:

rasa data convert nlu -f yaml --data <Dialogflow agent folder> --out <Rasa agent folder>

Now you have your NLU data! You can train an NLU model using rasa train nlu. What’s missing is rules and stories: Dialogflow has a different system of dialogue management that can’t be converted directly to Rasa format. 

Don’t worry: you only need a couple of short stories to train your first core model. Choose the simplest conversations that your agent should handle and try to write a couple of stories with 1-2 conversation turns. You can check out some examples of stories for various use cases (booking an appointment, reporting that something is broken, FAQs, etc) here: rasa-demo/data/stories at main · RasaHQ/rasa-demo · GitHub. You can train a full model now! From here, you can work iteratively: test your NLU and core components, see what intents and entities are not recognised correctly, add more examples. Write more rules and stories (remember that rasa interactive is of great help here) for the core model. Define your custom actions and add them to stories to make sure the model predicts them at the right time.

Conclusions

In this blog, we wanted to provide an introduction to chatbots in general and to show how to create Rasa agents, using an example of an AI driving assistant we developed. We hope that it will help you get through a few important steps of creating a Rasa chatbot: installation, creating a project, preparing data, choosing a config, training, adding custom actions. Enjoy developing your first Rasa bot!

Demo

Tagged: ChatbotsNLUPythonRasa Open Source

ACF

ID58157
keyfield_623341deec7d0
labelPhoto
namephoto
prefixacf
typeimage
valueArray ( [ID] => 69047 [id] => 69047 [title] => Omdena [filename] => logo-150x150-1.png [filesize] => 13764 [url] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [link] => https://omdena.com/blog/data-scientist-help/attachment/logo-150x150/ [alt] => Omdena [author] => 19 [description] => Omdena [caption] => Omdena [name] => logo-150x150 [status] => inherit [uploaded_to] => 20398 [date] => 2022-05-28 13:36:34 [modified] => 2022-07-29 10:31:29 [menu_order] => 0 [mime_type] => image/png [type] => image [subtype] => png [icon] => https://omdena.com/wp-includes/images/media/default.png [width] => 150 [height] => 150 [sizes] => Array ( [thumbnail] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1-150x150.png [thumbnail-width] => 96 [thumbnail-height] => 96 [medium] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [medium-width] => 150 [medium-height] => 150 [medium_large] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [medium_large-width] => 150 [medium_large-height] => 150 [large] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [large-width] => 150 [large-height] => 150 [1536x1536] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [1536x1536-width] => 150 [1536x1536-height] => 150 [2048x2048] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [2048x2048-width] => 150 [2048x2048-height] => 150 [et-pb-post-main-image] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-post-main-image-width] => 150 [et-pb-post-main-image-height] => 150 [et-pb-post-main-image-fullwidth] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-post-main-image-fullwidth-width] => 150 [et-pb-post-main-image-fullwidth-height] => 150 [et-pb-portfolio-image] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-portfolio-image-width] => 150 [et-pb-portfolio-image-height] => 150 [et-pb-portfolio-module-image] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-portfolio-module-image-width] => 150 [et-pb-portfolio-module-image-height] => 150 [et-pb-portfolio-image-single] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-portfolio-image-single-width] => 150 [et-pb-portfolio-image-single-height] => 150 [et-pb-gallery-module-image-portrait] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-gallery-module-image-portrait-width] => 150 [et-pb-gallery-module-image-portrait-height] => 150 [et-pb-post-main-image-fullwidth-large] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-post-main-image-fullwidth-large-width] => 150 [et-pb-post-main-image-fullwidth-large-height] => 150 [et-pb-image--responsive--desktop] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-image--responsive--desktop-width] => 150 [et-pb-image--responsive--desktop-height] => 150 [et-pb-image--responsive--tablet] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-image--responsive--tablet-width] => 150 [et-pb-image--responsive--tablet-height] => 150 [et-pb-image--responsive--phone] => https://omdena.com/wp-content/uploads/2021/02/logo-150x150-1.png [et-pb-image--responsive--phone-width] => 150 [et-pb-image--responsive--phone-height] => 150 ))
menu_order1
parent58155
wrapperArray ( [width] => [class] => [id] => )
return_formatarray
preview_sizethumbnail
libraryall
_namephoto
_valid1

Module Settings

custom_identifierImage
acf_namefield_623341deec7d0
is_author_acf_fieldoff
post_object_acf_namenone
author_field_typeauthor_post
linked_user_acf_namenone
type_taxonomy_acf_namenone
acf_tagdiv
show_labeloff
label_seperator:
visibilityon
empty_value_optionhide_module
use_iconoff
icon_color#7EBEC5
use_circleoff
circle_color#7EBEC5
use_circle_borderoff
circle_border_color#7EBEC5
use_icon_font_sizeoff
icon_image_placementleft
image_mobile_stackingcolumn
return_formatarray
image_link_urloff
image_link_url_acf_namenone
checkbox_stylearray
checkbox_radio_returnlabel
checkbox_radio_value_typeoff
checkbox_radio_linkoff
link_buttonoff
email_subjectnone
email_body_afternone
add_css_classoff
add_css_loop_layoutoff
add_css_class_selectorbody
link_new_tabon
link_name_acfoff
link_name_acf_namenone
url_link_iconoff
image_sizefull
true_false_conditionoff
true_false_condition_css_selector.et_pb_button
true_false_text_trueTrue
true_false_text_falseFalse
is_audiooff
is_videooff
video_loopon
video_autoplayon
is_oembed_videooff
defer_videooff
defer_video_iconI||divi||400
video_icon_font_sizeoff
pretify_textoff
pretify_seperator,
number_decimal.
show_value_if_zerooff
text_imageoff
is_options_pageoff
is_repeater_loop_layoutoff
linked_post_stylecustom
link_post_seperator,
link_to_post_objecton
loop_layoutnone
columns4
columns_tablet2
columns_mobile1
repeater_dyn_btn_acfnone
button_alignmentcenter
text_before_positionsame_line
label_positionsame_line
vertical_alignmentmiddle
image_max_width_last_editedon|phone
admin_labelPhoto
_builder_version4.16
_module_presetdefault
title_css_font_size14px
title_css_letter_spacing0px
title_css_line_height1em
acf_label_css_font_size14px
acf_label_css_letter_spacing0px
acf_label_css_line_height1em
label_css_letter_spacing0px
text_before_css_font_size14px
text_before_css_letter_spacing0px
text_before_css_line_height1em
seperator_font_size14px
seperator_letter_spacing0px
seperator_line_height1em
relational_field_item_font_size14px
relational_field_item_letter_spacing0px
relational_field_item_line_height1em
background_enable_coloron
use_background_color_gradientoff
background_color_gradient_repeatoff
background_color_gradient_typelinear
background_color_gradient_direction180deg
background_color_gradient_direction_radialcenter
background_color_gradient_stops#2b87da 0%|#29c4a9 100%
background_color_gradient_unit%
background_color_gradient_overlays_imageoff
background_color_gradient_start#2b87da
background_color_gradient_start_position0%
background_color_gradient_end#29c4a9
background_color_gradient_end_position100%
background_enable_imageon
parallaxoff
parallax_methodon
background_sizecover
background_image_widthauto
background_image_heightauto
background_positioncenter
background_horizontal_offset0
background_vertical_offset0
background_repeatno-repeat
background_blendnormal
background_enable_video_mp4on
background_enable_video_webmon
allow_player_pauseoff
background_video_pause_outside_viewporton
background_enable_pattern_styleoff
background_pattern_stylepolka-dots
background_pattern_colorrgba(0,0,0,0.2)
background_pattern_sizeinitial
background_pattern_widthauto
background_pattern_heightauto
background_pattern_repeat_origintop_left
background_pattern_horizontal_offset0
background_pattern_vertical_offset0
background_pattern_repeatrepeat
background_pattern_blend_modenormal
background_enable_mask_styleoff
background_mask_stylelayer-blob
background_mask_color#ffffff
background_mask_aspect_ratiolandscape
background_mask_sizestretch
background_mask_widthauto
background_mask_heightauto
background_mask_positioncenter
background_mask_horizontal_offset0
background_mask_vertical_offset0
background_mask_blend_modenormal
custom_buttonoff
button_text_size20
button_bg_use_color_gradientoff
button_bg_color_gradient_repeatoff
button_bg_color_gradient_typelinear
button_bg_color_gradient_direction180deg
button_bg_color_gradient_direction_radialcenter
button_bg_color_gradient_stops#2b87da 0%|#29c4a9 100%
button_bg_color_gradient_unit%
button_bg_color_gradient_overlays_imageoff
button_bg_color_gradient_start#2b87da
button_bg_color_gradient_start_position0%
button_bg_color_gradient_end#29c4a9
button_bg_color_gradient_end_position100%
button_bg_enable_imageon
button_bg_parallaxoff
button_bg_parallax_methodon
button_bg_sizecover
button_bg_image_widthauto
button_bg_image_heightauto
button_bg_positioncenter
button_bg_horizontal_offset0
button_bg_vertical_offset0
button_bg_repeatno-repeat
button_bg_blendnormal
button_bg_enable_video_mp4on
button_bg_enable_video_webmon
button_bg_allow_player_pauseoff
button_bg_video_pause_outside_viewporton
button_use_iconon
button_icon_placementright
button_on_hoveron
positioningnone
position_origin_atop_left
position_origin_ftop_left
position_origin_rtop_left
width100%
max_widthnone
max_width_tablet25%
max_width_phone25%
max_width_last_editedon|tablet
module_alignmentcenter
min_heightauto
heightauto
max_heightnone
custom_margin_tablet||0px||false|false
custom_margin_phone||0px||false|false
custom_margin_last_editedon|phone
filter_hue_rotate0deg
filter_saturate100%
filter_brightness100%
filter_contrast100%
filter_invert0%
filter_sepia0%
filter_opacity100%
filter_blur0px
mix_blend_modenormal
animation_stylenone
animation_directioncenter
animation_duration1000ms
animation_delay0ms
animation_intensity_slide50%
animation_intensity_zoom50%
animation_intensity_flip50%
animation_intensity_fold50%
animation_intensity_roll50%
animation_starting_opacity0%
animation_speed_curveease-in-out
animation_repeatonce
hover_transition_duration300ms
hover_transition_delay0ms
hover_transition_speed_curveease
link_option_url_new_windowoff
sticky_positionnone
sticky_offset_top0px
sticky_offset_bottom0px
sticky_limit_topnone
sticky_limit_bottomnone
sticky_offset_surroundingon
sticky_transitionon
motion_trigger_startmiddle
hover_enabled0
title_css_text_shadow_stylenone
title_css_text_shadow_horizontal_length0em
title_css_text_shadow_vertical_length0em
title_css_text_shadow_blur_strength0em
title_css_text_shadow_colorrgba(0,0,0,0.4)
acf_label_css_text_shadow_stylenone
acf_label_css_text_shadow_horizontal_length0em
acf_label_css_text_shadow_vertical_length0em
acf_label_css_text_shadow_blur_strength0em
acf_label_css_text_shadow_colorrgba(0,0,0,0.4)
label_css_text_shadow_stylenone
label_css_text_shadow_horizontal_length0em
label_css_text_shadow_vertical_length0em
label_css_text_shadow_blur_strength0em
label_css_text_shadow_colorrgba(0,0,0,0.4)
text_before_css_text_shadow_stylenone
text_before_css_text_shadow_horizontal_length0em
text_before_css_text_shadow_vertical_length0em
text_before_css_text_shadow_blur_strength0em
text_before_css_text_shadow_colorrgba(0,0,0,0.4)
seperator_text_shadow_stylenone
seperator_text_shadow_horizontal_length0em
seperator_text_shadow_vertical_length0em
seperator_text_shadow_blur_strength0em
seperator_text_shadow_colorrgba(0,0,0,0.4)
relational_field_item_text_shadow_stylenone
relational_field_item_text_shadow_horizontal_length0em
relational_field_item_text_shadow_vertical_length0em
relational_field_item_text_shadow_blur_strength0em
relational_field_item_text_shadow_colorrgba(0,0,0,0.4)
border_radiion|100%|100%|100%|100%
border_radii_tableton||||
border_radii_phoneon|100%|100%|100%|100%
border_radii_last_editedon|phone
button_text_shadow_stylenone
button_text_shadow_horizontal_length0em
button_text_shadow_vertical_length0em
button_text_shadow_blur_strength0em
button_text_shadow_colorrgba(0,0,0,0.4)
box_shadow_stylenone
box_shadow_colorrgba(0,0,0,0.3)
box_shadow_positionouter
box_shadow_style_buttonnone
box_shadow_color_buttonrgba(0,0,0,0.3)
box_shadow_position_buttonouter
text_shadow_stylenone
text_shadow_horizontal_length0em
text_shadow_vertical_length0em
text_shadow_blur_strength0em
text_shadow_colorrgba(0,0,0,0.4)
disabledoff
global_colors_info{}
Omdena

Execution time: 0.0045 seconds

ACF

ID58156
keyfield_623341caec7cf
labelName
nameblog_author_name
prefixacf
typetext
valueOmdena
parent58155
wrapperArray ( [width] => [class] => [id] => )
_nameblog_author_name
_valid1

Module Settings

custom_identifierACF Item
acf_namefield_623341caec7cf
is_author_acf_fieldoff
post_object_acf_namenone
author_field_typeauthor_post
linked_user_acf_namenone
type_taxonomy_acf_namenone
acf_tagp
show_labeloff
label_seperator:
visibilityon
empty_value_optionhide_module
use_iconoff
icon_color#7EBEC5
use_circleoff
circle_color#7EBEC5
use_circle_borderoff
circle_border_color#7EBEC5
use_icon_font_sizeoff
icon_image_placementleft
image_mobile_stackinginitial
return_formatarray
image_link_urloff
image_link_url_acf_namenone
checkbox_stylearray
checkbox_radio_returnlabel
checkbox_radio_value_typeoff
checkbox_radio_linkoff
link_buttonoff
email_subjectnone
email_body_afternone
add_css_classoff
add_css_loop_layoutoff
add_css_class_selectorbody
link_new_tabon
link_name_acfoff
link_name_acf_namenone
url_link_iconoff
image_sizefull
true_false_conditionoff
true_false_condition_css_selector.et_pb_button
true_false_text_trueTrue
true_false_text_falseFalse
is_audiooff
is_videooff
video_loopon
video_autoplayon
is_oembed_videooff
defer_videooff
defer_video_iconI||divi||400
video_icon_font_sizeoff
pretify_textoff
pretify_seperator,
number_decimal.
show_value_if_zerooff
text_imageoff
is_options_pageoff
is_repeater_loop_layoutoff
linked_post_stylecustom
link_post_seperator,
link_to_post_objecton
loop_layoutnone
columns4
columns_tablet2
columns_mobile1
repeater_dyn_btn_acfnone
text_before_positionsame_line
label_positionsame_line
vertical_alignmentmiddle
admin_labelName
_builder_version4.21.0
_module_presetdefault
title_css_text_alignleft
title_css_font_size14px
title_css_letter_spacing0px
title_css_line_height1em
acf_label_css_text_alignleft
acf_label_css_font_size14px
acf_label_css_letter_spacing0px
acf_label_css_line_height1em
label_css_fontRoboto|700|||||||
label_css_text_alignleft
label_css_letter_spacing0px
text_before_css_font_size14px
text_before_css_letter_spacing0px
text_before_css_line_height1em
seperator_font_size14px
seperator_letter_spacing0px
seperator_line_height1em
relational_field_item_font_size14px
relational_field_item_letter_spacing0px
relational_field_item_line_height1em
background_enable_coloron
use_background_color_gradientoff
background_color_gradient_repeatoff
background_color_gradient_typelinear
background_color_gradient_direction180deg
background_color_gradient_direction_radialcenter
background_color_gradient_stops#2b87da 0%|#29c4a9 100%
background_color_gradient_unit%
background_color_gradient_overlays_imageoff
background_color_gradient_start#2b87da
background_color_gradient_start_position0%
background_color_gradient_end#29c4a9
background_color_gradient_end_position100%
background_enable_imageon
parallaxoff
parallax_methodon
background_sizecover
background_image_widthauto
background_image_heightauto
background_positioncenter
background_horizontal_offset0
background_vertical_offset0
background_repeatno-repeat
background_blendnormal
background_enable_video_mp4on
background_enable_video_webmon
allow_player_pauseoff
background_video_pause_outside_viewporton
background_enable_pattern_styleoff
background_pattern_stylepolka-dots
background_pattern_colorrgba(0,0,0,0.2)
background_pattern_sizeinitial
background_pattern_widthauto
background_pattern_heightauto
background_pattern_repeat_origintop_left
background_pattern_horizontal_offset0
background_pattern_vertical_offset0
background_pattern_repeatrepeat
background_pattern_blend_modenormal
background_enable_mask_styleoff
background_mask_stylelayer-blob
background_mask_color#ffffff
background_mask_aspect_ratiolandscape
background_mask_sizestretch
background_mask_widthauto
background_mask_heightauto
background_mask_positioncenter
background_mask_horizontal_offset0
background_mask_vertical_offset0
background_mask_blend_modenormal
custom_buttonoff
button_text_size20
button_bg_use_color_gradientoff
button_bg_color_gradient_repeatoff
button_bg_color_gradient_typelinear
button_bg_color_gradient_direction180deg
button_bg_color_gradient_direction_radialcenter
button_bg_color_gradient_stops#2b87da 0%|#29c4a9 100%
button_bg_color_gradient_unit%
button_bg_color_gradient_overlays_imageoff
button_bg_color_gradient_start#2b87da
button_bg_color_gradient_start_position0%
button_bg_color_gradient_end#29c4a9
button_bg_color_gradient_end_position100%
button_bg_enable_imageon
button_bg_parallaxoff
button_bg_parallax_methodon
button_bg_sizecover
button_bg_image_widthauto
button_bg_image_heightauto
button_bg_positioncenter
button_bg_horizontal_offset0
button_bg_vertical_offset0
button_bg_repeatno-repeat
button_bg_blendnormal
button_bg_enable_video_mp4on
button_bg_enable_video_webmon
button_bg_allow_player_pauseoff
button_bg_video_pause_outside_viewporton
button_use_iconon
button_icon_placementright
button_on_hoveron
positioningnone
position_origin_atop_left
position_origin_ftop_left
position_origin_rtop_left
text_orientationleft
widthauto
max_widthnone
module_alignmentleft
min_heightauto
heightauto
max_heightnone
custom_margin_tablet||10px||false|false
custom_margin_phone||10px||false|false
custom_margin_last_editedon|tablet
custom_padding5px||||false|false
filter_hue_rotate0deg
filter_saturate100%
filter_brightness100%
filter_contrast100%
filter_invert0%
filter_sepia0%
filter_opacity100%
filter_blur0px
mix_blend_modenormal
animation_stylenone
animation_directioncenter
animation_duration1000ms
animation_delay0ms
animation_intensity_slide50%
animation_intensity_zoom50%
animation_intensity_flip50%
animation_intensity_fold50%
animation_intensity_roll50%
animation_starting_opacity0%
animation_speed_curveease-in-out
animation_repeatonce
hover_transition_duration300ms
hover_transition_delay0ms
hover_transition_speed_curveease
link_option_url_new_windowoff
sticky_positionnone
sticky_offset_top0px
sticky_offset_bottom0px
sticky_limit_topnone
sticky_limit_bottomnone
sticky_offset_surroundingon
sticky_transitionon
motion_trigger_startmiddle
hover_enabled0
title_css_text_align_tabletcenter
title_css_text_align_phonecenter
title_css_text_align_last_editedon|phone
acf_label_css_text_align_tabletcenter
acf_label_css_text_align_phonecenter
acf_label_css_text_align_last_editedon|phone
label_css_text_align_tabletcenter
label_css_text_align_phonecenter
label_css_text_align_last_editedon|desktop
text_orientation_tabletcenter
text_orientation_phonecenter
text_orientation_last_editedon|phone
module_alignment_tabletcenter
module_alignment_phonecenter
module_alignment_last_editedon|desktop
title_css_text_shadow_stylenone
title_css_text_shadow_horizontal_length0em
title_css_text_shadow_vertical_length0em
title_css_text_shadow_blur_strength0em
title_css_text_shadow_colorrgba(0,0,0,0.4)
acf_label_css_text_shadow_stylenone
acf_label_css_text_shadow_horizontal_length0em
acf_label_css_text_shadow_vertical_length0em
acf_label_css_text_shadow_blur_strength0em
acf_label_css_text_shadow_colorrgba(0,0,0,0.4)
label_css_text_shadow_stylenone
label_css_text_shadow_horizontal_length0em
label_css_text_shadow_vertical_length0em
label_css_text_shadow_blur_strength0em
label_css_text_shadow_colorrgba(0,0,0,0.4)
text_before_css_text_shadow_stylenone
text_before_css_text_shadow_horizontal_length0em
text_before_css_text_shadow_vertical_length0em
text_before_css_text_shadow_blur_strength0em
text_before_css_text_shadow_colorrgba(0,0,0,0.4)
seperator_text_shadow_stylenone
seperator_text_shadow_horizontal_length0em
seperator_text_shadow_vertical_length0em
seperator_text_shadow_blur_strength0em
seperator_text_shadow_colorrgba(0,0,0,0.4)
relational_field_item_text_shadow_stylenone
relational_field_item_text_shadow_horizontal_length0em
relational_field_item_text_shadow_vertical_length0em
relational_field_item_text_shadow_blur_strength0em
relational_field_item_text_shadow_colorrgba(0,0,0,0.4)
button_text_shadow_stylenone
button_text_shadow_horizontal_length0em
button_text_shadow_vertical_length0em
button_text_shadow_blur_strength0em
button_text_shadow_colorrgba(0,0,0,0.4)
box_shadow_stylenone
box_shadow_colorrgba(0,0,0,0.3)
box_shadow_positionouter
box_shadow_style_buttonnone
box_shadow_color_buttonrgba(0,0,0,0.3)
box_shadow_position_buttonouter
text_shadow_stylenone
text_shadow_horizontal_length0em
text_shadow_vertical_length0em
text_shadow_blur_strength0em
text_shadow_colorrgba(0,0,0,0.4)
disabledoff
global_colors_info{}

Omdena

Execution time: 0.0011 seconds

Execution time: 0.0005 seconds

ACF

ID58158
keyfield_6233420dec7d2
labelLinkedin URL
nameblog_linkedin_url
prefixacf
typeurl
valuehttp://www.linkedin.com/company/omdena
menu_order2
parent58155
wrapperArray ( [width] => [class] => [id] => )
_nameblog_linkedin_url
_valid1

Module Settings

custom_identifierLinkedin
acf_namefield_6233420dec7d2
is_author_acf_fieldoff
post_object_acf_namenone
author_field_typeauthor_post
linked_user_acf_namenone
type_taxonomy_acf_namenone
acf_tagspan
show_labeloff
label_seperator:
visibilityon
empty_value_optionhide_module
use_iconon
font_icon||divi||400
icon_color#0d8de2
use_circleoff
circle_color#7EBEC5
use_circle_borderoff
circle_border_color#7EBEC5
use_icon_font_sizeoff
icon_image_placementleft
image_mobile_stackinginitial
return_formaturl
image_link_urloff
image_link_url_acf_namenone
checkbox_stylearray
checkbox_radio_returnlabel
checkbox_radio_value_typeoff
checkbox_radio_linkoff
link_buttonoff
email_subjectnone
email_body_afternone
add_css_classoff
add_css_loop_layoutoff
add_css_class_selectorbody
link_new_tabon
link_name_acfoff
link_name_acf_namenone
url_link_iconon
image_sizefull
true_false_conditionoff
true_false_condition_css_selector.et_pb_button
true_false_text_trueTrue
true_false_text_falseFalse
is_audiooff
is_videooff
video_loopon
video_autoplayon
is_oembed_videooff
defer_videooff
defer_video_iconI||divi||400
video_icon_font_sizeoff
pretify_textoff
pretify_seperator,
number_decimal.
show_value_if_zerooff
text_imageoff
is_options_pageoff
is_repeater_loop_layoutoff
linked_post_stylecustom
link_post_seperator,
link_to_post_objecton
loop_layoutnone
columns4
columns_tablet2
columns_mobile1
repeater_dyn_btn_acfnone
button_alignmentleft
text_before_positionsame_line
label_positionsame_line
vertical_alignmentmiddle
admin_labelLinkedin
module_classlinkedin
_builder_version4.19.5
_module_presetdefault
title_css_text_alignleft
title_css_font_size14px
title_css_letter_spacing0px
title_css_line_height1em
acf_label_css_text_alignleft
acf_label_css_font_size14px
acf_label_css_letter_spacing0px
acf_label_css_line_height1em
label_css_text_alignleft
label_css_letter_spacing0px
text_before_css_font_size14px
text_before_css_letter_spacing0px
text_before_css_line_height1em
seperator_text_alignleft
seperator_font_size14px
seperator_letter_spacing0px
seperator_line_height1em
relational_field_item_text_alignleft
relational_field_item_font_size14px
relational_field_item_letter_spacing0px
relational_field_item_line_height1em
background_enable_coloron
use_background_color_gradientoff
background_color_gradient_repeatoff
background_color_gradient_typelinear
background_color_gradient_direction180deg
background_color_gradient_direction_radialcenter
background_color_gradient_stops#2b87da 0%|#29c4a9 100%
background_color_gradient_unit%
background_color_gradient_overlays_imageoff
background_color_gradient_start#2b87da
background_color_gradient_start_position0%
background_color_gradient_end#29c4a9
background_color_gradient_end_position100%
background_enable_imageon
parallaxoff
parallax_methodon
background_sizecover
background_image_widthauto
background_image_heightauto
background_positioncenter
background_horizontal_offset0
background_vertical_offset0
background_repeatno-repeat
background_blendnormal
background_enable_video_mp4on
background_enable_video_webmon
allow_player_pauseoff
background_video_pause_outside_viewporton
background_enable_pattern_styleoff
background_pattern_stylepolka-dots
background_pattern_colorrgba(0,0,0,0.2)
background_pattern_sizeinitial
background_pattern_widthauto
background_pattern_heightauto
background_pattern_repeat_origintop_left
background_pattern_horizontal_offset0
background_pattern_vertical_offset0
background_pattern_repeatrepeat
background_pattern_blend_modenormal
background_enable_mask_styleoff
background_mask_stylelayer-blob
background_mask_color#ffffff
background_mask_aspect_ratiolandscape
background_mask_sizestretch
background_mask_widthauto
background_mask_heightauto
background_mask_positioncenter
background_mask_horizontal_offset0
background_mask_vertical_offset0
background_mask_blend_modenormal
custom_buttonon
button_text_size14px
button_bg_use_color_gradientoff
button_bg_color_gradient_repeatoff
button_bg_color_gradient_typelinear
button_bg_color_gradient_direction180deg
button_bg_color_gradient_direction_radialcenter
button_bg_color_gradient_stops#2b87da 0%|#29c4a9 100%
button_bg_color_gradient_unit%
button_bg_color_gradient_overlays_imageoff
button_bg_color_gradient_start#2b87da
button_bg_color_gradient_start_position0%
button_bg_color_gradient_end#29c4a9
button_bg_color_gradient_end_position100%
button_bg_enable_imageon
button_bg_parallaxoff
button_bg_parallax_methodon
button_bg_sizecover
button_bg_image_widthauto
button_bg_image_heightauto
button_bg_positioncenter
button_bg_horizontal_offset0
button_bg_vertical_offset0
button_bg_repeatno-repeat
button_bg_blendnormal
button_bg_enable_video_mp4on
button_bg_enable_video_webmon
button_bg_allow_player_pauseoff
button_bg_video_pause_outside_viewporton
button_border_width0px
button_use_iconoff
button_icon_placementright
button_on_hoveron
button_custom_padding0px|0px|0px|0px|true|true
positioningnone
position_origin_atop_left
position_origin_ftop_left
position_origin_rtop_left
text_orientationleft
widthauto
max_widthnone
module_alignmentleft
min_heightauto
heightauto
max_heightnone
custom_margin_tablet||10px||false|false
custom_margin_phone||10px||false|false
custom_margin_last_editedon|tablet
filter_hue_rotate0deg
filter_saturate100%
filter_brightness100%
filter_contrast100%
filter_invert0%
filter_sepia0%
filter_opacity100%
filter_blur0px
mix_blend_modenormal
animation_stylenone
animation_directioncenter
animation_duration1000ms
animation_delay0ms
animation_intensity_slide50%
animation_intensity_zoom50%
animation_intensity_flip50%
animation_intensity_fold50%
animation_intensity_roll50%
animation_starting_opacity0%
animation_speed_curveease-in-out
animation_repeatonce
hover_transition_duration300ms
hover_transition_delay0ms
hover_transition_speed_curveease
link_option_url_new_windowoff
sticky_positionnone
sticky_offset_top0px
sticky_offset_bottom0px
sticky_limit_topnone
sticky_limit_bottomnone
sticky_offset_surroundingon
sticky_transitionon
motion_trigger_startmiddle
hover_enabled0
title_css_text_align_tabletcenter
title_css_text_align_phonecenter
title_css_text_align_last_editedon|phone
acf_label_css_text_align_tabletcenter
acf_label_css_text_align_phonecenter
acf_label_css_text_align_last_editedon|tablet
label_css_text_align_tabletcenter
label_css_text_align_phonecenter
label_css_text_align_last_editedon|desktop
relational_field_item_text_align_tabletcenter
relational_field_item_text_align_phonecenter
relational_field_item_text_align_last_editedon|tablet
text_orientation_tabletcenter
text_orientation_phonecenter
text_orientation_last_editedon|phone
module_alignment_tabletcenter
module_alignment_phonecenter
module_alignment_last_editedon|desktop
custom_css_main_elementdisplay:block;
title_css_text_shadow_stylenone
title_css_text_shadow_horizontal_length0em
title_css_text_shadow_vertical_length0em
title_css_text_shadow_blur_strength0em
title_css_text_shadow_colorrgba(0,0,0,0.4)
acf_label_css_text_shadow_stylenone
acf_label_css_text_shadow_horizontal_length0em
acf_label_css_text_shadow_vertical_length0em
acf_label_css_text_shadow_blur_strength0em
acf_label_css_text_shadow_colorrgba(0,0,0,0.4)
label_css_text_shadow_stylenone
label_css_text_shadow_horizontal_length0em
label_css_text_shadow_vertical_length0em
label_css_text_shadow_blur_strength0em
label_css_text_shadow_colorrgba(0,0,0,0.4)
text_before_css_text_shadow_stylenone
text_before_css_text_shadow_horizontal_length0em
text_before_css_text_shadow_vertical_length0em
text_before_css_text_shadow_blur_strength0em
text_before_css_text_shadow_colorrgba(0,0,0,0.4)
seperator_text_shadow_stylenone
seperator_text_shadow_horizontal_length0em
seperator_text_shadow_vertical_length0em
seperator_text_shadow_blur_strength0em
seperator_text_shadow_colorrgba(0,0,0,0.4)
relational_field_item_text_shadow_stylenone
relational_field_item_text_shadow_horizontal_length0em
relational_field_item_text_shadow_vertical_length0em
relational_field_item_text_shadow_blur_strength0em
relational_field_item_text_shadow_colorrgba(0,0,0,0.4)
button_text_shadow_stylenone
button_text_shadow_horizontal_length0em
button_text_shadow_vertical_length0em
button_text_shadow_blur_strength0em
button_text_shadow_colorrgba(0,0,0,0.4)
box_shadow_stylenone
box_shadow_colorrgba(0,0,0,0.3)
box_shadow_positionouter
box_shadow_style_buttonnone
box_shadow_color_buttonrgba(0,0,0,0.3)
box_shadow_position_buttonouter
text_shadow_stylenone
text_shadow_horizontal_length0em
text_shadow_vertical_length0em
text_shadow_blur_strength0em
text_shadow_colorrgba(0,0,0,0.4)
disabledoff
global_colors_info{}
custom_css_main_element_last_editedon|phone
custom_css_main_element_tabletdisplay:block;
custom_css_main_element_phonedisplay:block;

Execution time: 0.0020 seconds

Vetted Senior AI Talent

Work with our top 2% hidden gems, vetted through over 300 real-world projects.

Top Talent

Leave a comment.
0 Comments
Submit a Comment

Your email address will not be published. Required fields are marked *