Module 6 of 6 · 40 minutes

Project: analysing reviews with AI

Put it all together. You'll build a small but genuinely useful AI data pipeline — the kind analysts build every day.

Learning objectives

  • Combine pandas and an AI API in one workflow
  • Test AI processing on a sample before scaling
  • Check AI labels for errors
  • Summarise results and generate a brief
  • Apply good habits: environments, scripts, Git and data protection

6.1 The project: analyse customer reviews with AI

You'll combine everything: a DataFrame of reviews, a function that asks an AI model to classify each one, and pandas to summarise the results into insights a manager can act on.

ReviewsDataFrameTest on3 rowsAI classifieseach reviewChecklabelsSummarise(crosstab)Managerbrief
The project pipeline: test small, run, check the AI's work, then turn labels into insight.

6.2 Step 1 — the data

import pandas as pd

reviews = pd.DataFrame({
    "id": range(1, 9),
    "text": [
        "Gorgeous board, really solid. Arrived in two days.",
        "Took nearly three weeks to arrive and no tracking updates.",
        "Good quality but a bit expensive for the size.",
        "The handle on the spatula snapped after a week.",
        "Perfect gift, beautifully packaged!",
        "Courier left it in the rain, box soaked.",
        "Fine. Does the job.",
        "Customer service sorted my refund quickly, thank you.",
    ],
})

6.3 Step 2 — classify with AI (test small first)

sample = reviews.head(3).copy()
sample["result"] = sample["text"].apply(classify_review)      # from Module 5
print(sample)

# looks good? run on everything
reviews["result"] = reviews["text"].apply(classify_review)
results = pd.json_normalize(reviews["result"])                 # dict column -> columns
reviews = pd.concat([reviews.drop(columns="result"), results], axis=1)

6.4 Step 3 — check the AI's work

Never trust AI labels blindly (see Validating AI Output). Read a sample, count failures, and fix the prompt if needed:

print(reviews[["text", "sentiment", "topic"]])
print("Unparsed:", reviews["sentiment"].isna().sum())
print(reviews["topic"].value_counts())

6.5 Step 4 — summarise for a manager

table = pd.crosstab(reviews["topic"], reviews["sentiment"])
print(table)

negatives = reviews[reviews["sentiment"] == "negative"]["text"].tolist()
brief = ask("Write a 4-bullet summary for a shop manager of these negative reviews, "
            "with one suggested action each:\n- " + "\n- ".join(negatives))
print(brief)

6.6 Good habits as you grow

  • Virtual environments (python -m venv .venv) keep each project's packages separate
  • requirements.txt records the packages your project needs
  • Move from notebooks to scripts (.py files) for code you'll reuse
  • Version control with Git — but add secrets files to .gitignore
  • Small functions with clear names; test them on known inputs
  • Data protection — don't send personal data to APIs without a lawful basis and an approved provider

6.7 Where next?

You now have the Python foundations used throughout the technical courses. Next steps: Data Quality & Preparation, Machine Learning Fundamentals and Building LLM Applications with RAG.

Exercise: extend the project

Add a column urgent that is True when a review is negative and mentions delivery or damage, then print the urgent reviews for follow-up.

Show a solution
reviews["urgent"] = (reviews["sentiment"] == "negative") & reviews["text"].str.contains(
    "deliver|arriv|courier|damag|soaked|snapped", case=False)
print(reviews.loc[reviews["urgent"], ["id", "text"]])

Key takeaways

  • apply() runs a function over every row.
  • json_normalize turns dictionary results into columns.
  • Always check AI labels — count failures and read samples.
  • Cross-tabs turn labels into insight.
  • Virtual environments, scripts, Git and data protection keep projects healthy.