File size: 9,939 Bytes
b3eb597
 
 
 
ae6433b
a570ee2
ae6433b
ab778b5
6eb917c
66d546b
6eb917c
5983f67
1927724
fa015cf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bd2d8e4
c1344f9
1927724
fa015cf
 
 
 
 
 
 
 
c246bae
fa015cf
 
 
34d2248
 
087006d
8cfbb65
087006d
 
a570ee2
 
 
 
 
 
 
 
 
8cfbb65
a570ee2
 
 
087006d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8cfbb65
087006d
 
a570ee2
 
8cfbb65
a570ee2
 
 
8cfbb65
a570ee2
 
 
 
8cfbb65
a570ee2
 
 
34d2248
c246bae
087006d
2d3b7b6
 
90eec1e
b3eb597
 
162880f
b3eb597
 
 
8cfbb65
162880f
8cfbb65
 
ab778b5
0edf725
e68783d
 
0edf725
 
 
e68783d
 
0edf725
d0a4478
e68783d
 
 
fa015cf
0edf725
d0a4478
8cfbb65
 
13d2652
 
 
 
 
 
66d546b
3205271
66d546b
3205271
 
66d546b
fa015cf
 
 
 
 
 
 
 
 
 
3205271
 
 
 
bd3a924
66d546b
3205271
66d546b
 
 
 
 
 
 
1927724
6eb917c
1927724
6eb917c
 
 
1927724
6eb917c
fa015cf
 
6eb917c
 
fa015cf
6eb917c
 
66d546b
6eb917c
 
66d546b
e897e9d
764e1ed
1927724
cdb1b12
162880f
fa015cf
cdb1b12
2d3b7b6
c246bae
66d546b
 
2d3b7b6
c246bae
ae6bb9a
b3eb597
 
1927724
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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import gradio as gr
import pandas as pd
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
import re
from io import BytesIO
import tempfile
from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
import plotly.express as px
from PIL import Image

categories_keywords = {
    "Application Status": ["application status", "application", "status", "submitted", "processing", "pending", "approval", "rejected", "accepted"],
    "Volunteering": ["volunteer", "volunteering", "help out", "assist", "volunteer work", "volunteer opportunities"],
    "Certificates": ["certificate", "certificates", "completion", "certification", "accreditation", "proof", "document", "certified"],
    "Job Opportunities": ["job", "opportunity", "career", "vacancy", "position", "employment", "hiring", "recruitment", "internship"],
    "Surveys and Forms": ["survey", "form", "forms", "questionnaire", "feedback form", "response", "fill out", "submission"],
    "General Queries": ["hello", "hi", "help", "general", "query", "question", "info", "information", "inquiry", "ask"],
    "Spam": ["spam", "subscribe", "remove", "stop", "junk", "block", "opt-out", "watch my video", "click on this link", "win prize"],
    "Rescheduling and Postponing": ["reschedule", "postpone", "delay", "change date", "new time", "rearrange", "shift", "adjust timing"],
    "Contact and Communication Issues": ["contact", "communicate", "communication", "reach out", "phone", "email", "address", "details"],
    "Email and Credentials Issues": ["email", "credentials", "login", "password", "access", "username", "account", "verification", "reset"],
    "Timing and Scheduling": ["timing", "schedule", "scheduling", "time", "appointment", "availability", "calendar", "book", "slot"],
    "Salary and Benefits": ["salary", "benefits", "pay", "compensation", "wages", "earnings", "package", "remuneration", "incentives"],
    "Technical Issues": ["technical", "issue", "problem", "error", "bug", "glitch", "fix", "troubleshoot", "support"],
    "End of Conversation": ["bye", "thank you", "thanks", "goodbye", "see you", "later", "end", "close", "sign off"],
    "Start of Conversation": ["start", "begin", "hello", "hi", "initiate", "greet", "greeting", "open", "commence"],
    "Feedback": ["feedback", "comments", "review", "opinion", "suggestion", "critique", "rating"],
    "Online Meetings": ["meeting", "meeting code", "passcode", "join meeting", "zoom", "zoom link"],
    "Event Inquiries": ["event", "webinar", "meeting", "conference", "session", "seminar", "workshop", "invitation"],
    "Payment Issues": ["payment", "billing", "transaction", "charge", "fee", "invoice", "refund", "receipt"],
    "Registration Issues": ["registration", "register", "sign up", "enroll", "join", "signup", "enrollment"],
    "Service Requests": ["service", "support", "request", "assistance", "help", "aid", "maintenance"],
    "Account Issues": ["account", "profile", "update", "activation", "deactivation", "credentials", "reset"],
    "Product Information": ["product", "service", "details", "info", "information", "specifications", "features"],
    "Order Status": ["order", "status", "tracking", "shipment", "delivery", "purchase", "dispatch"],
    "Miscellaneous": []
}

def categorize_question(question):
    words = question.split()
    if len(words) == 1:
        single_word = words[0].lower()
        if any(single_word in keyword for keyword in categories_keywords["Start of Conversation"]):
            return "Start of Conversation"
        else:
            return "End of Conversation"
    
    for category, keywords in categories_keywords.items():
        if any(keyword.lower() in question.lower() for keyword in keywords):
            return category
    return "Miscellaneous"

def preprocess_data(df):
    df.rename(columns={'Question Asked': 'texts'}, inplace=True)
    df['texts'] = df['texts'].astype(str).str.lower()
    df['texts'] = df['texts'].apply(lambda text: re.sub(r'https?://\S+|www\.\S+', '', text))

    def remove_emoji(string):
        emoji_pattern = re.compile("["
                               u"\U0001F600-\U0001F64F"
                               u"\U0001F300-\U0001F5FF"
                               u"\U0001F680-\U0001F6FF"
                               u"\U0001F1E0-\U0001F1FF"
                               u"\U00002702-\U000027B0"
                               u"\U000024C2-\U0001F251"
                               "]+", flags=re.UNICODE)
        return emoji_pattern.sub(r'', string)

    df['texts'] = df['texts'].apply(remove_emoji)

    custom_synonyms = {
        'application': ['form'],
        'apply': ['fill', 'applied'],
        'work': ['job'],
        'salary': ['stipend', 'pay', 'payment', 'paid'],
        'test': ['online test', 'amcat test', 'exam', 'assessment'],
        'pass': ['clear', 'selected', 'pass or not'],
        'result': ['outcome', 'mark', 'marks'],
        'thanks': ["thanks a lot to you", "thankyou so much", "thank you so much", "tysm", "thank you",
                   "okaythank", "thx", "ty", "thankyou", "thank", "thank u"],
        'interview': ["pi"]
    }

    for original_word, synonym_list in custom_synonyms.items():
        for synonym in synonym_list:
            pattern = r"\b" + synonym + r"\b"
            df['texts'] = df['texts'].str.replace(pattern, original_word, regex=True)

    spam_list = ["click here", "free", "recharge", "limited", "discount", "money back guarantee", "aaj", "kal", "mein",
                 "how can i help you", "how can we help you", "how we can help you", "follow", "king", "contacting", "gar",
                 "kirke", "subscribe", "youtube", "jio", "insta", "make money", "b2b", "sent using truecaller"]

    for spam_phrase in spam_list:
        pattern = r"\b" + re.escape(spam_phrase) + r"\b"
        df = df[~df['texts'].str.contains(pattern)]

    def remove_punctuations(text):
        return re.sub(r'[^\w\s]', '', text)

    df['texts'] = df['texts'].apply(remove_punctuations)
    df['texts'] = df['texts'].str.strip()
    df = df[df['texts'] != '']

    df['Category'] = df['texts'].apply(categorize_question)

    return df

def cluster_data(df, num_clusters):
    vectorizer = TfidfVectorizer(stop_words='english')
    X = vectorizer.fit_transform(df['texts'])

    kmeans = KMeans(n_clusters=num_clusters, random_state=0)
    kmeans.fit(X)
    df['Cluster'] = kmeans.labels_

    return df, kmeans

def generate_wordcloud(df):
    text = " ".join(df['texts'].tolist())
    stopwords = set(STOPWORDS)
    wordcloud = WordCloud(
        width=800,
        height=400,
        background_color='white',
        max_words=300,
        collocations=False,
        min_font_size=10,
        max_font_size=200,
        stopwords=stopwords,
        prefer_horizontal=1.0,
        scale=2,
        relative_scaling=0.5,
        random_state=42
    ).generate(text[:1000000])  # Limit the text length to 1,000,000 characters to avoid memory issues
    
    plt.figure(figsize=(15, 7))
    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    buf = BytesIO()
    plt.savefig(buf, format='png')
    buf.seek(0)
    img = Image.open(buf)
    return img

def generate_bar_chart(df, num_clusters_to_display):
    common_words = {'i', 'you', 'thanks', 'thank', 'ok', 'okay', 'sure', 'done'}
    
    top_categories = df['Category'].value_counts().index[:num_clusters_to_display]
    df_top_categories = df[df['Category'].isin(top_categories)]
    
    def extract_top_words(texts, n=1):
        vec = TfidfVectorizer(stop_words='english').fit(texts)
        sum_words = vec.transform(texts).sum(axis=0)
        words_freq = [(word, sum_words[0, idx]) for word, idx in vec.vocabulary_.items()]
        sorted_words = sorted(words_freq, key=lambda x: x[1], reverse=True)
        return [word for word, freq in sorted_words if word not in common_words][:n]

    category_top_words = df_top_categories.groupby('Category')['texts'].apply(lambda texts: extract_top_words(texts, 3)).reset_index()
    category_top_words['top_word'] = category_top_words['texts'].apply(lambda words: ', '.join(words))
    
    category_sizes = df_top_categories['Category'].value_counts().reset_index()
    category_sizes.columns = ['Category', 'Count']
    category_sizes = category_sizes.merge(category_top_words[['Category', 'top_word']], on='Category')
    
    fig = px.bar(category_sizes, x='Category', y='Count', text='top_word', title='Category Frequency with Top Words')
    fig.update_traces(textposition='outside')
    fig.update_layout(xaxis_title='Category', yaxis_title='Frequency', showlegend=False)
    
    buf = BytesIO()
    fig.write_image(buf, format='png')
    buf.seek(0)
    img = Image.open(buf)
    return img

def main(file, num_clusters_to_display):
    try:
        df = pd.read_csv(file)
        
        df = df[df['Answer'] == 'Fallback Message shown']
        
        df = preprocess_data(df)
        
        wordcloud_img = generate_wordcloud(df)
        bar_chart_img = generate_bar_chart(df, num_clusters_to_display)

        with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as tmpfile:
            df.to_csv(tmpfile.name, index=False)
            csv_file_path = tmpfile.name

        return csv_file_path, wordcloud_img, bar_chart_img
    except Exception as e:
        print(f"Error: {e}")
        return str(e), None, None

interface = gr.Interface(
    fn=main,
    inputs=[
        gr.File(label="Upload CSV File (.csv)"),
        gr.Slider(label="Number of Categories to Display", minimum=1, maximum=15, step=1, value=5)
    ],
    outputs=[
        gr.File(label="Categorized Data CSV"),
        gr.Image(label="Word Cloud"),
        gr.Image(label="Bar Chart")
    ],
    title="Unanswered User Queries Categorization",
    description="Categorize unanswered user queries into predefined categories"
)

interface.launch(share=True)