ZennyKenny commited on
Commit
208794f
·
verified ·
1 Parent(s): 6c660b0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +166 -93
app.py CHANGED
@@ -1,105 +1,178 @@
1
- import os
2
  import gradio as gr
3
- from huggingface_hub import InferenceClient
 
4
  import spaces
5
 
6
- # Load API token from environment variable
7
- API_TOKEN = os.getenv("API_TOKEN")
8
-
9
- if not API_TOKEN:
10
- raise ValueError("API_TOKEN environment variable is not set.")
11
-
12
- client = InferenceClient(model="mistralai/Mistral-Nemo-Instruct-2407", token=API_TOKEN)
13
-
14
- SYSTEM_MESSAGE = ("""
15
- Your name is Monty, and you represent montebello.ai. Your goal is to engage customers about montebello.ai’s AI solutions and encourage them to either schedule a call by clicking the "Call Me" button or by calling (415)-862-1695.
16
-
17
- **About montebello.ai:**
18
- We provide affordable, tailored AI solutions for small businesses, helping them save time, reduce costs, and improve efficiency.
19
-
20
- **Our Services:**
21
- - **AI Phone Assistant:** Set up in days for as little as $200/month to handle calls, customer inquiries, and appointment scheduling.
22
- - **Data Insights:** Analyze sales, inventory, and customer behavior for smarter business decisions.
23
- - **Productivity Boost:** Streamline workflows to free up your team’s time.
24
- - **Customer Experience:** Enhance engagement with AI-powered chatbots and personalized marketing.
25
-
26
- **Your Approach:**
27
- 1. **Start by Asking:**
28
- - 'What would you like to know about montebello.ai?'
29
-
30
- 2. **Provide Specific Examples:**
31
- - 'An AI Phone Agent can save you hours each week by handling common inquiries.’
32
- - 'An AI Email Agent can reduce the amount of incoming emails that your team needs to handle by a significant amount.'
33
- - 'An AI Appointment Agent can help you manage your time in the most effective way possible, freeing you up to work with your customers.'
34
-
35
-
36
- 3. **Highlight Affordability and Speed:**
37
- - 'We can set up you AI Agent in just a few days for as little as $200/month.’
38
-
39
- 4. **Encourage Action:**
40
- - 'To experience our AI Phone Agent firsthand, call (415)-862-1695.’
41
- - 'To experience our AI Email Agent firsthand, write us at [email protected].’
42
-
43
- **Tone and Style:**
44
- - Friendly, energetic, and professional.
45
- - Keep responses very concise and focused on solving their problems.
46
- - Avoid technical jargon unless the customer is familiar with AI.
47
-
48
- **Closing:**
49
- End by reiterating how montebello.ai can help and encourage them to take the next step by calling us, emailing us, or setting up an appointment.
50
- """)
51
-
52
 
53
- MAX_TOKENS = 256
54
- TEMPERATURE = 0.7
55
- TOP_P = 0.95
56
-
57
- # @spaces.GPU
58
- def respond(message, history: list[tuple[str, str]]):
59
- messages = [{"role": "system", "content": SYSTEM_MESSAGE}]
60
-
61
- for val in history:
62
- if val[0]:
63
- messages.append({"role": "user", "content": val[0]})
64
- if val[1]:
65
- messages.append({"role": "assistant", "content": val[1]})
66
-
67
- messages.append({"role": "user", "content": message})
68
-
69
- response = ""
70
- for message in client.chat_completion(
71
- messages,
72
- max_tokens=MAX_TOKENS,
73
- stream=True,
74
- temperature=TEMPERATURE,
75
- top_p=TOP_P,
76
- ):
77
- token = message.choices[0].delta.content
78
- response += token
79
- yield response
80
 
81
- # Custom CSS
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  custom_css = """
83
- body {
84
- background-color: #f9d029 !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  }
86
  footer {
87
  visibility: hidden;
88
  }
89
- .submit-button {
90
- background-color: #f9d029 !important;
91
- color: #000000 !important;
92
- border: none !important;
93
- border-radius: 5px;
94
- padding: 10px 20px;
95
- font-weight: bold;
96
- }
97
- .submit-button:hover {
98
- background-color: #e6b800 !important;
99
- }
100
  """
101
 
102
- montebello = gr.ChatInterface(respond, css=custom_css)
103
-
104
- if __name__ == "__main__":
105
- montebello.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ from transformers import pipeline
3
+ import pandas as pd
4
  import spaces
5
 
6
+ # Load dataset
7
+ from datasets import load_dataset
8
+ ds = load_dataset('ZennyKenny/demo_customer_nps')
9
+ df = pd.DataFrame(ds['train'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # Initialize model pipeline
12
+ from huggingface_hub import login
13
+ import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
+ # Login using the API key stored as an environment variable
16
+ hf_api_key = os.getenv("API_KEY")
17
+ login(token=hf_api_key)
18
+
19
+ classifier = pipeline("text-classification", model="distilbert/distilbert-base-uncased-finetuned-sst-2-english")
20
+ generator = pipeline("text2text-generation", model="google/flan-t5-base")
21
+
22
+ # Function to classify customer comments
23
+ @spaces.GPU
24
+ def classify_comments(categories):
25
+ global df # Ensure we're modifying the global DataFrame
26
+ sentiments = []
27
+ assigned_categories = []
28
+ for comment in df['customer_comment']:
29
+ # Classify sentiment
30
+ sentiment = classifier(comment)[0]['label']
31
+ # Generate category
32
+ category_str = ', '.join(categories)
33
+ prompt = f"What category best describes this comment? '{comment}' Please answer using only the name of the category: {category_str}."
34
+ category = generator(prompt, max_length=30)[0]['generated_text']
35
+ assigned_categories.append(category)
36
+ sentiments.append(sentiment)
37
+ df['comment_sentiment'] = sentiments
38
+ df['comment_category'] = assigned_categories
39
+ return df.to_html(index=False) # Return all fields with appended sentiment and category
40
+
41
+ # Function to add a category
42
+ def add_category(categories, new_category):
43
+ if new_category.strip() != "" and len(categories) < 5: # Limit to 5 categories
44
+ categories.append(new_category.strip())
45
+ return categories, "", f"**Categories:**\n" + "\n".join([f"- {cat}" for cat in categories])
46
+
47
+ # Function to reset categories
48
+ def reset_categories():
49
+ return [], "**Categories:**\n- None"
50
+
51
+ # Function to load data from uploaded CSV
52
+ def load_data(file):
53
+ global df # Ensure we're modifying the global DataFrame
54
+ if file is not None:
55
+ file.seek(0) # Reset file pointer
56
+ if file.name.endswith('.csv'):
57
+ custom_df = pd.read_csv(file, encoding='utf-8')
58
+ else:
59
+ return "Error: Uploaded file is not a CSV."
60
+ # Check for required columns
61
+ required_columns = ['customer_comment']
62
+ if not all(col in custom_df.columns for col in required_columns):
63
+ return f"Error: Uploaded CSV must contain the following column: {', '.join(required_columns)}"
64
+ df = custom_df
65
+ return "Custom CSV loaded successfully!"
66
+ else:
67
+ return "No file uploaded."
68
+
69
+ # Function to use template categories
70
+ def use_template():
71
+ template_categories = ["Product Experience", "Customer Support", "Price of Service", "Other"]
72
+ return template_categories, f"**Categories:**\n" + "\n".join([f"- {cat}" for cat in template_categories])
73
+
74
+ # Custom CSS for button styling
75
  custom_css = """
76
+ button {
77
+ background-color: #4c6bfd !important;
78
+ border: none !important;
79
+ color: white !important;
80
+ padding: 10px 20px !important;
81
+ text-align: center !important;
82
+ text-decoration: none !important;
83
+ display: inline-block !important;
84
+ font-size: 16px !important;
85
+ border-radius: 5px !important;
86
+ transition: background-color 0.3s ease !important;
87
+ }
88
+
89
+ button:hover {
90
+ background-color: #3a52cc !important;
91
  }
92
  footer {
93
  visibility: hidden;
94
  }
 
 
 
 
 
 
 
 
 
 
 
95
  """
96
 
97
+ # Gradio Interface
98
+ with gr.Blocks(css=custom_css) as nps:
99
+ # State to store categories
100
+ categories = gr.State([])
101
+
102
+ # App title
103
+ gr.Markdown("# 🎉 Customer Comment Classifier 🎉")
104
+
105
+ # Short explanation
106
+ gr.Markdown("""
107
+ This app classifies customer comments into categories and assigns sentiment labels (Positive/Negative).
108
+ You can upload your own dataset or use the provided template. The app will append the generated
109
+ `comment_sentiment` and `comment_category` fields to your dataset.
110
+ """)
111
+
112
+ # File upload and instructions
113
+ with gr.Row():
114
+ with gr.Column(scale=1):
115
+ uploaded_file = gr.File(label="📂 Upload CSV", type="filepath", scale=1)
116
+ with gr.Column(scale=1):
117
+ gr.Markdown("""
118
+ **📝 Instructions:**
119
+ - Upload a CSV file with at least one column: `customer_comment`.
120
+ - If you don't have your own data, click **Use Template** to load a sample dataset.
121
+ """)
122
+ template_btn = gr.Button("✨ Use Template", size="sm")
123
+
124
+ gr.Markdown("---")
125
+
126
+ # Category section
127
+ with gr.Row():
128
+ with gr.Column(scale=1):
129
+ # Category input and buttons
130
+ category_input = gr.Textbox(label="📝 New Category", placeholder="Enter category name", scale=1)
131
+ with gr.Row():
132
+ add_category_btn = gr.Button("➕ Add Category", size="sm")
133
+ reset_btn = gr.Button("🔄 Reset Categories", size="sm")
134
+ # Category display
135
+ category_status = gr.Markdown("**📂 Categories:**\n- None")
136
+ with gr.Column(scale=1):
137
+ gr.Markdown("""
138
+ **📝 Instructions:**
139
+ - Enter a category name and click **Add Category** to add it to the list.
140
+ - Click **Reset Categories** to clear the list.
141
+ - The `customer_comment` field will be categorized based on the categories you provide.
142
+ """)
143
+
144
+ gr.Markdown("---")
145
+
146
+ # Classify button and output
147
+ with gr.Row():
148
+ with gr.Column(scale=1):
149
+ classify_btn = gr.Button("🔍 Classify", size="sm")
150
+ with gr.Column(scale=3): # Center the container and make it 75% of the window width
151
+ output = gr.HTML()
152
+
153
+ # Event handlers
154
+ add_category_btn.click(
155
+ fn=add_category,
156
+ inputs=[categories, category_input],
157
+ outputs=[categories, category_input, category_status]
158
+ )
159
+ reset_btn.click(
160
+ fn=reset_categories,
161
+ outputs=[categories, category_status]
162
+ )
163
+ uploaded_file.change(
164
+ fn=load_data,
165
+ inputs=uploaded_file,
166
+ outputs=output
167
+ )
168
+ template_btn.click(
169
+ fn=use_template,
170
+ outputs=[categories, category_status]
171
+ )
172
+ classify_btn.click(
173
+ fn=classify_comments,
174
+ inputs=categories,
175
+ outputs=output
176
+ )
177
+
178
+ nps.launch(share=True)