File size: 5,003 Bytes
cbcd78b
1ea874c
be195b7
 
4530b74
be195b7
 
 
 
cbcd78b
be195b7
 
 
1ea874c
be195b7
 
 
 
 
 
1ea874c
be195b7
ec6871c
67df231
962079a
3fac692
67df231
cbcd78b
67df231
0a5100e
67df231
 
9d03f28
3fac692
67df231
3fac692
 
67df231
3b076ac
cbcd78b
278f543
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cbcd78b
 
713fa8b
 
 
bf3b2cd
 
9d03f28
bf3b2cd
 
 
 
 
 
511d4e8
bf3b2cd
9d32e7a
bf3b2cd
 
 
 
 
 
 
 
80cfb3b
bf3b2cd
be195b7
bf3b2cd
 
 
 
 
 
 
 
67df231
8d2cc8a
bf3b2cd
 
 
1ea874c
be195b7
8d2cc8a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cbcd78b
8d2cc8a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
import gradio as gr
from transformers import pipeline
import pandas as pd
import spaces

# Load dataset
from datasets import load_dataset
ds = load_dataset('ZennyKenny/demo_customer_nps')
df = pd.DataFrame(ds['train'])

# Initialize model pipeline
from huggingface_hub import login
import os

# Login using the API key stored as an environment variable
hf_api_key = os.getenv("API_KEY")
login(token=hf_api_key)

classifier = pipeline("text-classification", model="distilbert/distilbert-base-uncased-finetuned-sst-2-english")
generator = pipeline("text2text-generation", model="google/flan-t5-base")

# Function to classify customer comments
@spaces.GPU
def classify_comments(categories):
    global df  # Ensure we're modifying the global DataFrame
    sentiments = []
    assigned_categories = []
    for comment in df['customer_comment']:
        # Classify sentiment
        sentiment = classifier(comment)[0]['label']
        # Generate category
        category_str = ', '.join(categories)
        prompt = f"What category best describes this comment? '{comment}' Please answer using only the name of the category: {category_str}."
        category = generator(prompt, max_length=30)[0]['generated_text']
        assigned_categories.append(category)
        sentiments.append(sentiment)
    df['comment_sentiment'] = sentiments
    df['comment_category'] = assigned_categories
    return df.to_html(index=False)  # Return all fields with appended sentiment and category

# Function to add a category
def add_category(categories, new_category):
    if new_category.strip() != "" and len(categories) < 5:  # Limit to 5 categories
        categories.append(new_category.strip())
    return categories, "", f"**Categories:**\n" + "\n".join([f"- {cat}" for cat in categories])

# Function to reset categories
def reset_categories():
    return [], "**Categories:**\n- None"

# Function to load data from uploaded CSV
def load_data(file):
    global df  # Ensure we're modifying the global DataFrame
    if file is not None:
        file.seek(0)  # Reset file pointer
        if file.name.endswith('.csv'):
            custom_df = pd.read_csv(file, encoding='utf-8')
        else:
            return "Error: Uploaded file is not a CSV."
        # Check for required columns
        required_columns = ['customer_comment']
        if not all(col in custom_df.columns for col in required_columns):
            return f"Error: Uploaded CSV must contain the following column: {', '.join(required_columns)}"
        df = custom_df
        return "Custom CSV loaded successfully!"
    else:
        return "No file uploaded."

# Function to use template categories
def use_template():
    template_categories = ["Product Experience", "Customer Support", "Price of Service", "Other"]
    return template_categories, f"**Categories:**\n" + "\n".join([f"- {cat}" for cat in template_categories])

# Gradio Interface
with gr.Blocks() as nps:
    # State to store categories
    categories = gr.State([])

    # App title
    gr.Markdown("# Customer Comment Classifier")

    # Short explanation
    gr.Markdown("""
    This app classifies customer comments into categories and assigns sentiment labels (Positive/Negative). 
    You can upload your own dataset or use the provided template. The app will append the generated 
    `comment_sentiment` and `comment_category` fields to your dataset.
    """)

    # File upload and instructions
    with gr.Row():
        with gr.Column(scale=1):
            uploaded_file = gr.File(label="Upload CSV", type="filepath", scale=1)
        with gr.Column(scale=2):
            gr.Markdown("""
            **Instructions:**
            - Upload a CSV file with at least one column: `customer_comment`.
            - If you don't have your own data, click **Use Template** to load a sample dataset.
            """)

    # Template button
    template_btn = gr.Button("Use Template")

    # Category widgets
    with gr.Row():
        with gr.Column():
            category_input = gr.Textbox(label="New Category", placeholder="Enter category name")
            add_category_btn = gr.Button("Add Category")
            reset_btn = gr.Button("Reset Categories")
            category_status = gr.Markdown("**Categories:**\n- None")

    # Classify button
    classify_btn = gr.Button("Classify", size="sm")

    # Output
    output = gr.HTML()

    # Event handlers
    add_category_btn.click(
        fn=add_category,
        inputs=[categories, category_input],
        outputs=[categories, category_input, category_status]
    )
    reset_btn.click(
        fn=reset_categories,
        outputs=[categories, category_status]
    )
    uploaded_file.change(
        fn=load_data,
        inputs=uploaded_file,
        outputs=output
    )
    template_btn.click(
        fn=use_template,
        outputs=[categories, category_status]
    )
    classify_btn.click(
        fn=classify_comments,
        inputs=categories,
        outputs=output
    )

nps.launch(share=True)