How to build an interactive, shareable sentiment analysis dashboard with MotherDuck & Fabi.ai
2025/02/12 - 12 min read
BYText analysis presents unique challenges for businesses trying to understand customer feedback. Analyzing survey responses or product reviews can improve your customer experience. But, at the same time, extracting insights from unstructured text data is complex and time-consuming.
Large Language Models (LLMs) and Small Language Models (SMLs) excel at this task. However, integrating them into real-time, business-ready dashboards requires careful consideration of performance, cost, and usability.
Thankfully, MotherDuck is uniquely well-suited for this task for two reasons:
- It’s a highly-performant, cost-effective data warehouse designed for analytics use cases.
- It’s the only data warehouse with a built-in language model that can take in arbitrary prompts to enrich and manipulate data on the fly
Adding on, Fabi.ai–an AI data analytics platform with SQL, Python, and AI support–perfectly complements MotherDuck. Fabi.ai provides the fastest way in the market to go from raw data to interactive, shareable reports.
This tutorial will show you how to use MotherDuck's prompt() function and vector embeddings, along with Fabi.ai's visualizations. We'll label data for sentiment analysis and create an interactive dashboard to improve your customer experience.
What we’ll build: An interactive sentiment analysis dashboard
By the end of this article, you’ll know how to build an end-to-end sentiment analysis process, including:
- A MotherDuck query that analyzes a free-form review field and categorizes reviews as “Positive”, “Neutral”, or “Negative.”
- An interactive dashboard that shows reviews and insights based on review sentiment and product category.
- Dynamic filtering capabilities for product categories and sentiment types.
- A semantic search function using vector embeddings for intelligent review discovery.
- An automated refresh system to keep your analysis current.
To see the end result in action, check out our video:
What is sentiment analysis, and what makes it challenging?
Sentiment analysis is a technique in natural language processing that identifies and categorizes opinions or emotions expressed in text. It checks if the sentiment is positive, negative, or neutral and is often used to analyze customer feedback, social media, or reviews. This helps businesses and researchers understand public sentiment and make data-driven decisions about their products. Sentiment analysis is also a powerful tool for customer success and marketing teams because it can help them identify issues with their services or products, and understand what customers and users like about their offerings.
In our example, sentiment analysis means categorizing customer product reviews into “Positive”, “Neutral,” or “Negative” categories.
Traditional sentiment analysis methods, like rule-based systems and ML models, often struggle with context, sarcasm, and adapting to new domains. Rule-based approaches rely on lexicons. But they often fail with nuanced language, while ML methods require extensive labeled data and feature engineering. This limits their generalizability. For example, a review that says “I wanted to love this product but in the end I regretted it” is clearly negative. A human reader would easily glean that. But traditional sentiment analysis methods might misclassify it because of the word “love.”
Language models overcome these challenges. They can understand context, handle subtleties like sarcasm, and generalize across domains. Pretrained on diverse text from sources rich in emotions and sarcasm (comment sections, we’re looking at you), these language models easily capture nuanced sentiment, adapt to new domains, and support multilingual analysis with minimal additional training. All of which make them highly effective for sentiment analysis tasks.
Meet prompt(): MotherDuck’s built-in small language model
In the second half of 2024, MotherDuck introduced a powerful new prompt() function. Prompt() lets you use language models directly in your MotherDuck queries.
Here’s a simple example:
Copy code
SELECT prompt('summarize my text: ' || my_text) as summary FROM my_table;
This query summarizes text in a “my_text” field and inserts it into a “summary” field in the results.
Prompt() leverages OpenAI's GPT-4o mini and GPT-4o models trained specifically for MotherDuck’s use case and is optimized for cost and performance. It’s well suited for extraction from unstructured fields in your MotherDuck tables.
Instructions: How to build a sentiment analysis dashboard with MotherDuck and Fabi.ai
OK, it’s time to get into our example: Building our sentiment analysis dashboard. It will extract the sentiment from customer product reviews for a fictional company, Superdope, which sells fashion apparel. We’ll use that information to build a product review dashboard that you can share with your customer success and marketing teams.
We’ll complete this in a few steps:
- Use prompt() in MotherDuck to prepare the data and extract sentiment from a review text field.
- Query the review and sentiment data in Fabi.ai and then build and extract the insights.
- Build a dashboard from your Fabi.ai Smartbook and publish the dashboard.
Environment requirements
Before we get started, here are the technical requirements you’ll need going into this example:
- A MotherDuck account with access to prompt() and embedding() functions. These are part of the Standard plan.
- Some text data in a CSV file.
- A Fabi.ai account for dashboard creation. You can use the Free Tier of the product for this.
- Basic SQL knowledge.
- Basic Python knowledge.
1. Create our sentiment analysis pipeline
This example will use synthetic data for our fictional company, which you can download yourself here if you’d like to follow along exactly. Otherwise, you can simply ask your favorite AI to generate some data for you with the following fields:
- product_category: Categories of products (e.g. shoes, t-shirts, swimwear)
- review: A text field containing some review data ranging from positive to negative
- rating: A score from 0 to 10
Once you have your data, go ahead and upload it to your MotherDuck instance.
Using prompt() to create derivative fields
Once your data is loaded into your database, check that it’s there. Next, we’ll generate two fields: A sentiment field, which will simply be “Positive”, “Neutral” or “Negative”, and a keywords field, which contains keywords from the review.
Using prompt():
Copy code
SELECT
product_category as category,
review,
rating,
prompt('Classify sentiment as "Positive", "Negative", "Neutral". Just use those simple terms: ' || Review ) as sentiment,
prompt('Extract keywords from review as a comma separated list: ' || Review ) as keywords
FROM my_db.main.superdope_product_reviews;
Your results should have the sentiment in the sentiment field. This prompt worked for us, but you may need to tune it a little bit to get the results you want. For example, when I first didn’t specify “Just use those simple terms” it was using “Neutral sentiment” as a category. You may also want to consider some simple evals and errors when building this in production in the event that the AI decides to behave a bit differently.
2. Analyze your data in Fabi.ai
Now that we have our data loaded in MotherDuck and our query in hand, let’s conduct our analysis in Fabi.ai. We’ll create a table and a pie chart with some filters so your stakeholders can adjust the view on their own.
Follow these steps:
Step 1: Log in to Fabi.ai and create your account
Go to https://app.fabi.ai/ and log in with your corporate Gmail account.
Step 2: Connect MotherDuck to Fabi.ai
When you create your account, the system will prompt you to connect your data source.. Simply follow those steps and enter your MotherDuck access token. Or, in a blank Smartbook in the Schema browser, click on the “Add Data Source” option on the left hand side and follow those same steps.
Step 3: Query the data
In a blank Smartbook, create a new SQL cell and copy/paste the SQL query we wrote above. Run the cell. You should see the results in the output. Note: This data is now cached as a pandas DataFrame. This is important for the following steps.
![motherduck_query.png](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2Fmotherduck_query_fad6b5a2e5.png&w=3840&q=75)
Step 4: Chain a new SQL cell and create filters
In this step, we’re going to query the DataFrame generated by the SQL cell. Under the first SQL cell, create another new SQL cell and query the DataFrame:
Copy code
select * from dataframe1
This step may seem redundant, but it helps when creating filters. Since dataframe1 is now cached, we can create dynamic filters based on the values in the result.
In your second SQL cell, we can adjust the query to add a dynamic variable:
Copy code
select *
from dataframe1
where sentiment in {{sentiment}}
Now let’s create the filter for sentiment. Above the second SQL cell, click “Insert a new cell” and create a Filters & Inputs of type Pick List. Follow the steps using the following parameters:
- Input Name: sentiment
- Options Type: dynamic
- Dataframe: dataframe1
- Column: sentiment
- Allow multiple selections: True
In our example, we added two filters, but this is what you should now see (below). If you change the filter or rerun the cell, it will pick up the values from the dropdown. You can create many more types of filters and inputs in Fabi.ai.
![filtered_dataframe.png](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2Ffiltered_dataframe_1e6f6c1cca.png&w=3840&q=75)
Step 5: Create a pie chart
Finally, let’s create a pie chart. It will show the distribution of sentiment for the filtered DataFrame.
At the bottom of the Smartbook, insert a new Python cell. Use Plotly to create a pie chart with dataframe2 (the DataFrame generated by your second SQL cell):
Copy code
import plotly.express as px
sentiment_counts = dataframe2['sentiment'].value_counts()
# Create a dictionary to map sentiments to specific colors
color_map = {'Positive': '#A5D6A7', 'Negative': '#FF8A80', 'Neutral': '#BCAAA4'}
colors = [color_map[sentiment] for sentiment in sentiment_counts.index]
fig = px.pie(values=sentiment_counts.values,
names=sentiment_counts.index,
width=800,
height=450,
color_discrete_sequence=colors)
fig.update_layout(title='Distribution of Review Sentiments')
fig.show()
Run that cell, and there you have it! Your pie chart will dynamically adjust as you change the filters above.
![sentiment_pie_chart.png](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2Fsentiment_pie_chart_6451fc6d35.png&w=3840&q=75)
Pro-tip: Fabi.ai has an integrated AI assistant that can write both SQL and Python and understands the full context of your Smartbook. Rather than writing the code manually, you can simply ask the AI.
3. Build and publish the report and share with stakeholders
Congrats, you’ve successfully categorized product review sentiment using MotherDuck! We’ve also built a basic sentiment analysis. Now we need to convert this to a shareable report for your teammates.
In the top header of the Smartbook, click “Report.” This will take you to the report building staging area. There, you can add, remove, or rearrange elements as you wish. In our case, you can remove the first SQL cell output. It's a duplicate of the second one but without the filter. In the right-hand configuration pane, you can schedule this report to refresh as well.
When you’re ready to publish this, click Publish in the right hand panel, which will bring you to the report.
And that’s it! Now you can share this URL with your coworkers. They’ll be able to slice and dice product reviews by sentiment on their own.
![fabi_sentiment_dashboard.png](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2Ffabi_sentiment_dashboard_e9e1041412.png&w=3840&q=75)
Bonus: Use MotherDuck’s vector embedding for advanced review search
If you’re building a sentiment analysis report, you may also want to let your users search reviews by content. Keyword and term matching using things like Regex or even fuzzy matching can be quite limiting. Say, for example, you want to search for reviews that mention “great quality.” It would be great if that search could return a review that says “The materials were top notch,” which is clearly a commentary on the quality.
MotherDuck’s vector embedding can offer a quick and easy way to build a clever search engine.
In the same Smartbook we created above, create a new SQL cell and add the following MotherDuck query:
Copy code
WITH embedded_reviews AS (
SELECT
product_category AS category,
review,
rating,
embedding(review) AS review_embedding
FROM my_db.main.superdope_product_reviews
),
search_query AS (
SELECT embedding('great quality') AS query_embedding
)
SELECT
er.category,
er.review,
er.rating,
array_cosine_similarity(er.review_embedding, sq.query_embedding) AS similarity_score
FROM embedded_reviews er, search_query sq
ORDER BY similarity_score DESC
The embedding() function will create an embedding for each review. It does this as a new column called review_embedding in the CTE. Then we use cosine similarity to match that embedding with the embedding for the string ‘great quality’.
Now, to create a search function for your users in the dashboard, replace the ‘great quality’ string with a parameter:
Copy code
WITH embedded_reviews AS (
SELECT
product_category AS category,
review,
rating,
embedding(review) AS review_embedding
FROM my_db.main.superdope_product_reviews
),
search_query AS (
SELECT embedding('{{search_term}}') AS query_embedding
)
SELECT
er.category,
er.review,
er.rating,
array_cosine_similarity(er.review_embedding, sq.query_embedding) AS similarity_score
FROM embedded_reviews er, search_query sq
ORDER BY similarity_score DESC
LIMIT 10
For this to run, we’ll create a new input above this cell like we did previously for the filter. Select “Insert a new cell” above the SQL cell and select Text. Call the input “search_term” and insert some default value. After creating this input, you can search for any term in it. It will then perform a semantic search on the review field.
![Screenshot 2025-02-10 at 1.47.14 PM.png](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2FScreenshot_2025_02_10_at_1_47_14_PM_af9cdd1ee8.png&w=3840&q=75)
Further learning: Customizing our sentiment analysis
A few final, quick tips and thoughts to take your analysis to the next level:
- Prompt tuning: You may need to play around with the prompt a bit to make sure it’s giving you the results you want reliably. Smaller models are powerful but may need a bit more supervision than larger models. It’s also best to keep the prompt short and precise. As a best practice, consider adding some basic checks and error handling or evals. In our example here, if the AI doesn’t return exactly “Positive”, “Neutral”, or “Negative”, that should be identified and handled gracefully.
- Advanced visualization: This tutorial uses a simple bar chart. But, using Plotly and Python, you can customize your Fabi.ai report to your heart’s content. Have some fun exploring creative ways to show off your data!
- Precomputing vector embedding: If you know the field you want to perform a semantic search in, consider precomputing the vector embedding directly in MotherDuck to improve performance.
- DuckDB caching: Not only does Fabi.ai integrate with MotherDuck, but it also uses DuckDB as part of its caching layer. When we created the second SQL cell, it referenced the DataFrame from the first SQL query output. That data was being stored in DuckDB, which means queries on Python DataFrames have all the benefits of DuckDB.
Next steps
With that, you’re now a sentiment analysis expert! This tutorial explored how to use MotherDuck’s native prompt() function to parse out natural language on the fly and leverage Fabi.ai to build an interactive, shareable report for your customer success and marketing teams. This is a great way to stay on top of reviews and improve your customer experience.
Check out the full tutorial walkthrough, or get started with your own data in MotherDuck today.
CONTENT
- What we’ll build: An interactive sentiment analysis dashboard
- What is sentiment analysis, and what makes it challenging?
- Meet prompt(): MotherDuck’s built-in small language model
- Instructions: How to build a sentiment analysis dashboard with MotherDuck and Fabi.ai
- Further learning: Customizing our sentiment analysis
Start using MotherDuck now!
![blog subscription icon](/_next/image/?url=%2F_next%2Fstatic%2Fmedia%2Fblog-subscription-icon.67ccd5ae.png&w=828&q=75)
PREVIOUS POSTS
![DuckDB Ecosystem: February 2025](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2Fduckdbecosystem_February_6c95914c9a.png&w=3840&q=75)
2025/02/09 - Simon Späti
DuckDB Ecosystem: February 2025
DuckDB Monthly #25: DuckCon highlights, DuckDB vs DataFusion and more!
![MotherDuck for Business Analytics: GDPR, SOC 2 Type II, Tiered Support, and New Plan Offerings](/_next/image/?url=https%3A%2F%2Fmotherduck-com-web-prod.s3.amazonaws.com%2Fassets%2Fimg%2FPricing_v2_1_f4d4004588.png&w=3840&q=75)
2025/02/11 - MotherDuck team
MotherDuck for Business Analytics: GDPR, SOC 2 Type II, Tiered Support, and New Plan Offerings
Introducing new features designed to better support businesses looking for their first data warehouse, including SOC 2 Type II and GDPR compliance, tiered support, read scaling, and a new Business Plan.