Skip to content

Retail and consumer goodsBI, AI and ML for the business

Reviews and tickets read every night

Reviews and support tickets say what is wrong long before the sales figures do, but there are too many to read them all. In Muvia a Python function gives every message a topic and a tone each night, and Athena sums up the main problems with the figures and what to do.

Illustrative scenario: it describes a typical case, not a customer project.

Customers write it down before sales show it.

A leaking bottle, a product nowhere to be found, a late courier: customers write it in reviews and support tickets weeks before the problem reaches the sales figures. But there are thousands of messages, and whoever reads them only sees a part.

Without a topic and a tone for every message you cannot see when an issue flares up, on which products, and whether the fix worked. Complaints stay anecdotes.

Who it's for
Customer care and quality, marketing and brand, product managers.
Online store reviews from a REST API, support tickets in CSV files and the product list in Excel flow into Muvia, where a Python function gives every message a topic and a tone each night; out come the table of classified messages, a dashboard of topics week by week, an alarm on negative messages and Athena's answers.

In Muvia, step by step

Real product screens, recorded on a project with sample data.

1 of 5

The video · Reviews and support tickets say what is wrong long before the sales figures do, but there are too many to read them all. In Muvia a Python function gives every message a topic and a tone each night, and Athena sums up the main problems with the figures and what to do.

What you get

Every message read
Every review and every ticket has a topic and a tone, not just the ones somebody had time to open.
Problems seen as they start
An issue that lights up on the heatmap shows in the week it happens, with the products involved.
You see whether the fix works
After a correction, the tone and the complaints on that topic tell you week by week whether the problem is solved.
From summary to action
Athena turns thousands of messages into a few problems, with the figures and what to do about each.

For the technical team

How it is built in Muvia

  1. 1

    Load reviews and tickets

    Reviews come from a REST API, tickets from files appended to the same table. Every message carries its text, date, channel and product.

  2. 2

    Classify in Python

    A Python function reads every text with an Italian lexicon and a few rules: the topic is the group of keywords that appears most, the tone runs from −1 to +1 and accounts for negations and stars. It runs in the sandboxed runtime, with no network.

  3. 3

    Schedule the recomputation

    A flow runs the function every night at 2 and writes each message's topic, tone and keywords to a managed table.

  4. 4

    Build the dashboard

    The topic-by-week heatmap shows when an issue lights up; next to it sit the average tone, the share of negative messages and the products involved.

  5. 5

    Ask Athena

    Athena reads the classified messages and answers with the main problems: how many negative messages, the worst week, the products involved and what to do.

Python function

import re
import pandas as pd

# The lexicon is Italian because the messages are
TOPICS = {
    "Packaging": ["tappo", "bottiglia", "confezione", "perde"],
    "Availability": ["introvabile", "esaurit", "scaffal"],
    "Delivery": ["consegna", "corriere", "spedizione"],
    "Taste": ["gusto", "sapore", "frizzant"],
}
POSITIVE = ("ottim", "buon", "perfett", "pratic", "puntual")
NEGATIVE = ("perde", "rovesciat", "ritardo", "esaurit", "pessim")
NEGATIONS = {"non", "mai", "nessun"}

def _topic(text):
    hits = {t: sum(text.count(w) for w in words) for t, words in TOPICS.items()}
    best = max(hits, key=hits.get)
    return best if hits[best] else "Other"

def _tone(text):
    words, signs = re.findall(r"[a-zàèéìòù]+", text), []
    for i, w in enumerate(words):
        s = 1 if w.startswith(POSITIVE) else -1 if w.startswith(NEGATIVE) else 0
        if s and i > 0 and words[i - 1] in NEGATIONS:
            s = -s
        if s:
            signs.append(s)
    return sum(signs) / len(signs) if signs else 0.0

def transform(inputs, params, ctx):
    m = inputs["rows"].copy()
    texts = m["text"].fillna("").str.lower()
    m["topic"] = texts.map(_topic)
    tone = texts.map(_tone)
    stars, weight = pd.to_numeric(m["stars"], errors="coerce"), params["star_weight"]
    m["tone_score"] = tone.where(stars.isna(), (1 - weight) * tone + weight * (stars - 3) / 2).round(2)
    return {"rows": m}
Topic and tone from a lexicon and a few rules your team writes: you can read them, fix them and run them again.
The data it needs
  • Online store reviews with text and stars, read through a REST API
  • Support tickets with text, product and province, from CSV files
  • Products and formats, from an Excel file
Parts of Muvia used

Bring us a question you can't answer today.

We start from a real question your business has and walk the path from source to dashboard with your systems, not a demo dataset.