Ajay98 commited on
Commit
9d2179d
Β·
verified Β·
1 Parent(s): 2906120

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +404 -99
app.py CHANGED
@@ -11,125 +11,430 @@ from fuzzywuzzy import process
11
  SALESFORCE_USERNAME = os.getenv("SALESFORCE_USERNAME")
12
  SALESFORCE_PASSWORD = os.getenv("SALESFORCE_PASSWORD")
13
  SALESFORCE_SECURITY_TOKEN = os.getenv("SALESFORCE_SECURITY_TOKEN")
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- # Initialize PaddleOCR
16
- ocr = PaddleOCR(use_angle_cls=True, lang='en')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
- # Product names list for fuzzy matching
19
- PRODUCT_NAMES = ["Honda Activa", "Yamaha R15", "Suzuki Access", "Hero Splendor"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
 
21
- # Salesforce Object Mapping
22
- OBJECT_MAPPING = {
23
- "Entry_Sales": ("VENKATA_RAMANA_MOTORS__c", "Quantity__c"),
24
- "Entry_NonSales": ("UNBILLING_DATA__c", "TotalQuantity__c"),
25
- "Exit_Sales": ("Inventory_Management__c", "Quantity_Sold__c"),
26
- "Exit_NonSales": ("Un_Billable__c", "Sold_Out__c"),
27
- }
28
 
29
- # Extract text from image
30
  def extract_text(image):
31
  result = ocr.ocr(image)
32
- return "\n".join([line[1][0] for line in result[0]])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
- # Fuzzy match product name
35
- def match_product_name(text):
36
- match, score = process.extractOne(text, PRODUCT_NAMES)
37
- return match if score >= 70 else "Unknown"
 
38
 
39
- # Salesforce Interaction
 
 
 
 
 
 
40
  def interact_with_salesforce(mode, entry_type, quantity, extracted_text):
41
  try:
42
- sf = Salesforce(username=SALESFORCE_USERNAME, password=SALESFORCE_PASSWORD, security_token=SALESFORCE_SECURITY_TOKEN)
43
- obj_key = f"{mode}_{entry_type}"
44
- object_name, field_name = OBJECT_MAPPING.get(obj_key, (None, None))
45
-
46
- if not object_name:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  return "Invalid mode or entry type."
48
-
 
 
 
 
 
 
49
  product_name = match_product_name(extracted_text)
50
- query = f"SELECT Id, {field_name} FROM {object_name} WHERE Product_Name__c = '{product_name}' LIMIT 1"
51
- response = sf.query(query)
52
-
53
- if mode == "Exit" and response["records"]:
54
- record = response["records"][0]
55
- record_id = record["Id"]
56
- new_quantity = max(0, int(record[field_name]) - quantity)
57
- sf.__getattr__(object_name).update(record_id, {field_name: new_quantity})
58
- return f"Updated {object_name}: New {field_name} = {new_quantity}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  else:
60
- sf.__getattr__(object_name).create({"Product_Name__c": product_name, field_name: quantity})
61
- return f"βœ… Data exported to {object_name}."
62
  except Exception as e:
63
- return f"❌ Salesforce Error: {str(e)}"
64
 
65
- # Process image and update Salesforce
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  def process_image(image, mode, entry_type, quantity):
67
  extracted_text = extract_text(image)
 
 
 
 
 
 
 
 
 
68
  message = interact_with_salesforce(mode, entry_type, quantity, extracted_text)
69
- return f"Extracted Text:\n{extracted_text}\n\n{message}"
70
 
71
- # Fetch Salesforce Data & Generate Graph
72
- def fetch_salesforce_data():
73
- try:
74
- sf = Salesforce(username=SALESFORCE_USERNAME, password=SALESFORCE_PASSWORD, security_token=SALESFORCE_SECURITY_TOKEN)
75
- query = "SELECT Product_Name__c, Current_Stocks__c FROM Inventory_Management__c"
76
-
77
- # Log the query being executed
78
- response = sf.query_all(query)
79
-
80
- # If no records found
81
- if not response['records']:
82
- return "No data found in Salesforce."
83
-
84
- df = pd.DataFrame(response["records"]).drop(columns=['attributes'], errors='ignore')
85
- df.rename(columns={"Product_Name__c": "Product Name", "Current_Stocks__c": "Stock Quantity"}, inplace=True)
86
-
87
- # Create a dynamic and interactive bar chart
88
- fig = px.bar(df, x="Product Name", y="Stock Quantity",
89
- title="Stock Distribution",
90
- labels={"Product Name": "Products", "Stock Quantity": "Quantity"},
91
- hover_data=["Product Name", "Stock Quantity"],
92
- color="Stock Quantity",
93
- color_continuous_scale='Viridis')
94
-
95
- # Make the chart more interactive with hover
96
- fig.update_traces(texttemplate='%{x}: %{y}', textposition='outside', hovertemplate='%{x}: %{y} units')
97
-
98
- # Layout adjustments
99
- fig.update_layout(
100
- hovermode='closest',
101
- xaxis_title="Product",
102
- yaxis_title="Stock Quantity",
103
- template="plotly_dark",
104
- showlegend=False
105
- )
106
-
107
- return fig.to_html(full_html=False)
108
- except Exception as e:
109
- return f"Error fetching Salesforce data: {str(e)}"
110
 
111
- # Gradio Interface with Colorful UI Template
112
  def app():
113
- with gr.Blocks(theme="huggingface") as interface:
114
- gr.Markdown("<h1 style='color:#2A9D8F;'>🏒 VENKATARAMANA MOTORS</h1>")
115
-
116
- with gr.Tab("πŸ“₯ Stock Entry & Processing"):
117
- with gr.Row():
118
- image_input = gr.Image(type="numpy", label="πŸ“„ Upload Image")
119
- mode_dropdown = gr.Dropdown(label="πŸ“Œ Mode", choices=["Entry", "Exit"], value="Entry")
120
- entry_type_radio = gr.Radio(label="πŸ“¦ Entry Type", choices=["Sales", "Non-Sales"], value="Sales")
121
- quantity_input = gr.Number(label="πŸ”’ Quantity", value=1)
122
- submit_button = gr.Button("πŸ” Process Image", style={"background-color": "#2A9D8F", "color": "white"})
123
-
124
- result_output = gr.Text(label="πŸ“ Processed Result")
125
- submit_button.click(fn=process_image, inputs=[image_input, mode_dropdown, entry_type_radio, quantity_input], outputs=result_output)
126
-
127
- with gr.Tab("πŸ“Š Salesforce Data Overview"):
128
- fetch_button = gr.Button("⚑ Fetch Salesforce Data", style={"background-color": "#E9C46A", "color": "white"})
129
- salesforce_graph = gr.HTML(label="πŸ“‰ Stock Graph")
130
- fetch_button.click(fn=fetch_salesforce_data, inputs=[], outputs=[salesforce_graph])
131
-
132
- return interface
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
 
134
  if __name__ == "__main__":
135
- app().launch(share=True)
 
11
  SALESFORCE_USERNAME = os.getenv("SALESFORCE_USERNAME")
12
  SALESFORCE_PASSWORD = os.getenv("SALESFORCE_PASSWORD")
13
  SALESFORCE_SECURITY_TOKEN = os.getenv("SALESFORCE_SECURITY_TOKEN")
14
+ import os
15
+ from paddleocr import PaddleOCR
16
+ from PIL import Image
17
+ import gradio as gr
18
+ import requests
19
+ import re
20
+ from simple_salesforce import Salesforce
21
+ import pandas as pd
22
+ import matplotlib.pyplot as plt
23
+ from io import BytesIO
24
+ from fuzzywuzzy import process
25
 
26
+ #πŸ“Œ Attribute mappings: readable names to Salesforce API names
27
+ ATTRIBUTE_MAPPING = {
28
+ "Product name": "Productname__c",
29
+ "Colour": "Colour__c",
30
+ "Motortype": "Motortype__c",
31
+ "Frequency": "Frequency__c",
32
+ "Grossweight": "Grossweight__c",
33
+ "Ratio": "Ratio__c",
34
+ "MotorFrame": "Motorframe__c",
35
+ "Model": "Model__c",
36
+ "Speed": "Speed__c",
37
+ "Quantity": "Quantity__c",
38
+ "Voltage": "Voltage__c",
39
+ "Material": "Material__c",
40
+ "Type": "Type__c",
41
+ "Horsepower": "Horsepower__c",
42
+ "Consignee": "Consignee__c",
43
+ "LOT": "LOT__c",
44
+ "Stage": "Stage__c",
45
+ "Outlet": "Outlet__c",
46
+ "Serialnumber": "Serialnumber__c",
47
+ "HeadSize": "Headsize__c",
48
+ "Deliverysize": "Deliverysize__c",
49
+ "Phase": "Phase__c",
50
+ "Size": "Size__c",
51
+ "MRP": "MRP__c",
52
+ "Usebefore": "Usebefore__c",
53
+ "Height": "Height__c",
54
+ "MaximumDischarge Flow": "Maximumdischargeflow__c",
55
+ "DischargeRange": "Dischargeflow__c",
56
+ "Assembledby": "Manufacturer__c",
57
+ "Manufacturedate": "Manufacturedate__c",
58
+ "Companyname": "Companyname__c",
59
+ "Customercarenumber": "Customercarenumber__c",
60
+ "SellerAddress": "Selleraddress__c",
61
+ "Selleremail": "Selleremail__c",
62
+ "GSTIN": "GSTIN__c",
63
+ "Totalamount": "Totalamount__c",
64
+ "Paymentstatus": "Paymentstatus__c",
65
+ "Paymentmethod": "Paymentstatus__c",
66
+ "Invoicedate": "Manufacturedate__c",
67
+ "Warranty": "Warranty__c",
68
+ "Brand": "Brand__c",
69
+ "Motorhorsepower": "Motorhorsepower__c",
70
+ "Power": "Power__c",
71
+ "Motorphase": "Motorphase__c",
72
+ "Enginetype": "Enginetype__c",
73
+ "Tankcapacity": "Tankcapacity__c",
74
+ "Head": "Head__c",
75
+ "Usage/Application": "Usage_Application__c",
76
+ "Volts": "volts__c",
77
+ "Hertz": "Hertz__c",
78
+ "Frame": "frame__c",
79
+ "Mounting": "Mounting__c",
80
+ "Tollfreenumber": "Tollfreenumber__c",
81
+ "Pipesize": "Pipesize__c",
82
+ "Manufacturer": "Manufacturer__c",
83
+ "Office": "Office__c",
84
+ "SRnumber": "SRnumber__c",
85
+ "TypeOfEndUse": "TypeOfEndUse__c",
86
+ "Model Name": "Model_Name_Number__c",
87
+ "coolingmethod": "coolingmethod__c"
88
+ }
89
 
90
+ # List of product names to match
91
+ PRODUCT_NAMES = [
92
+ "Centrifugal mono block pump", "SINGLE PHASE MOTOR STARTER", "EasyPact EZC 100",
93
+ "Openwell Submersible Pumpset", "Electric Motor", "Self Priming Pump",
94
+ "Control panel for single phase submersible pumps", "MOTOR", "Submersible pump set",
95
+ "Fusion submersible pump set", "DCT", "Shock proof water proof", "CG COMMERCIAL MOTORS", "Fusion",
96
+ "control panel for single phase submerisible pumps",
97
+ "single phase digital starter dry run and timer panel", "5HP AV1 XL Kirloskar Pump",
98
+ "Phase stainless steel submersible pump", "Submersible pump", "WB15X",
99
+ "Vtype self priming pump", "SP SHINE DISC", "havells submersible pump",
100
+ "Havells open well Submersible pump", "Bertolini pump CK3 90pp",
101
+ "WPA 772 Water Pump Assy", "bertolini TTL triplex high pressure plunger pumps",
102
+ "Generic plunger high pressure pump", "Apple Normal, Banana",
103
+ "Cast Iron KSb centrifugal pump", "5.5kw Water Pump",
104
+ "KSB reliable i line centrifuged pumps", "Apple Normal, Orange, Banana",
105
+ "Positive API 6745 hydraulic diaphragm pump", "1/2 inch Fuel Hose Pipe", "Kirloskar Water Pump",
106
+ "Rotodel motor pump", "PVC Electrical Insulation Materials",
107
+ "Electric kirloskar domestic water pump", "Electrical Insulation Materials",
108
+ "sellowell motor pump", "bhupathi submersible pump set",
109
+ "Flowshine Submersible pump set", "Index submersible pump",
110
+ "Wintoss Plastic Electric Switch Board", "Electric 18 watt ujagar cooler pump",
111
+ "Generator Service", "LG WM FHT1207ZWL, LG REF GL-S292RSCY",
112
+ "Water tank, Filters, Water Pump", "MS Control Submersible Panel",
113
+ "Centrifugal Monoblock Pumps", "Electric Motor with Pump BodyBlue and White",
114
+ "Various Repair and Maintenance Parts", "Earthmax Pump",
115
+ "Water Tank, Filters, Water Pump", "Centrifugal Water Pump for Agriculture",
116
+ "mono block pumps"
117
+ ]
118
 
119
+ #🧠 Initialize PaddleOCR
120
+ ocr = PaddleOCR(use_angle_cls=True, lang='en')
 
 
 
 
 
121
 
122
+ # Function to extract text using PaddleOCR
123
  def extract_text(image):
124
  result = ocr.ocr(image)
125
+ extracted_text = []
126
+ for line in result[0]:
127
+ extracted_text.append(line[1][0])
128
+ return "\n".join(extracted_text)
129
+
130
+ # Function to match product name using fuzzy matching
131
+ def match_product_name(extracted_text):
132
+ best_match = None
133
+ best_score = 0
134
+
135
+ for line in extracted_text.split("\n"):
136
+ match, score = process.extractOne(line, PRODUCT_NAMES)
137
+ if score > best_score:
138
+ best_match = match
139
+ best_score = score
140
+
141
+ return best_match if best_score >= 70 else None # Threshold of 70 for a match
142
+
143
+ # Function to extract attributes and their values
144
+ def extract_attributes(extracted_text):
145
+ attributes = {}
146
 
147
+ for readable_attr, sf_attr in ATTRIBUTE_MAPPING.items():
148
+ pattern = rf"{re.escape(readable_attr)}[:\-]?\s*(.+)"
149
+ match = re.search(pattern, extracted_text, re.IGNORECASE)
150
+ if match:
151
+ attributes[readable_attr] = match.group(1).strip()
152
 
153
+ return attributes
154
+
155
+ # Function to filter attributes for valid Salesforce fields
156
+ def filter_valid_attributes(attributes, valid_fields):
157
+ return {ATTRIBUTE_MAPPING[key]: value for key, value in attributes.items() if ATTRIBUTE_MAPPING[key] in valid_fields}
158
+
159
+ #πŸ“Š Function to interact with Salesforce based on mode and type
160
  def interact_with_salesforce(mode, entry_type, quantity, extracted_text):
161
  try:
162
+ sf = Salesforce(
163
+ username=SALESFORCE_USERNAME,
164
+ password=SALESFORCE_PASSWORD,
165
+ security_token=SALESFORCE_SECURITY_TOKEN
166
+ )
167
+
168
+ # Mapping mode and entry_type to Salesforce object and field
169
+ object_name = None
170
+ field_name = None
171
+ product_field_name = "Product_Name__c" # Correct field for product name in the object
172
+ model_field_name = "Modal_Name__c" # Correct field for model name in the object
173
+
174
+ if mode == "Entry":
175
+ if entry_type == "Sales":
176
+ object_name = "VENKATA_RAMANA_MOTORS__c"
177
+ field_name = "Quantity__c"
178
+ elif entry_type == "Non-Sales":
179
+ object_name = "UNBILLING_DATA__c"
180
+ field_name = "TotalQuantity__c"
181
+ elif mode == "Exit":
182
+ if entry_type == "Sales":
183
+ object_name = "Inventory_Management__c"
184
+ product_field_name = "Product_Name__c"
185
+ model_field_name = "Modal_Name__c"
186
+ field_name = "Quantity_Sold__c"
187
+ elif entry_type == "Non-Sales":
188
+ object_name = "Un_Billable__c"
189
+ product_field_name = "Product_Name__c"
190
+ model_field_name = "Model_Name__c"
191
+ field_name = "Sold_Out__c"
192
+
193
+ if not object_name or not field_name:
194
  return "Invalid mode or entry type."
195
+
196
+ # Get valid fields for the specified Salesforce object
197
+ sf_object = sf.__getattr__(object_name)
198
+ schema = sf_object.describe()
199
+ valid_fields = {field["name"] for field in schema["fields"]}
200
+
201
+ # Extract product name or model number
202
  product_name = match_product_name(extracted_text)
203
+ attributes = extract_attributes(extracted_text)
204
+
205
+ if not product_name:
206
+ return "Product name could not be matched from the extracted text."
207
+
208
+ attributes["Product name"] = product_name
209
+
210
+ if mode == "Exit":
211
+ query = f"SELECT Id, {field_name} FROM {object_name} WHERE {product_field_name} = '{product_name}' OR {model_field_name} = '{attributes.get('Model Name', '')}' LIMIT 1"
212
+ response = sf.query(query)
213
+
214
+ if response["records"]:
215
+ record_id = response["records"][0]["Id"]
216
+ updated_quantity = quantity # Overwrite the quantity, don't add
217
+ sf_object.update(record_id, {field_name: updated_quantity})
218
+ return f"Updated record for product '{product_name}' in {object_name}. New {field_name}: {updated_quantity}."
219
+ else:
220
+ return f"No matching record found for product '{product_name}' in {object_name}."
221
+ else:
222
+ filtered_attributes = filter_valid_attributes(attributes, valid_fields)
223
+ filtered_attributes[field_name] = quantity
224
+ sf_object.create(filtered_attributes)
225
+ return f"βœ… Data successfully exported to Salesforce object {object_name}."
226
+
227
+ except Exception as e:
228
+ return f"❌ Error interacting with Salesforce: {str(e)}"
229
+
230
+ # Function to pull data from Salesforce MotorDataAPI
231
+ def pull_data_from_motor_api():
232
+ try:
233
+ sf = Salesforce(
234
+ username=SALESFORCE_USERNAME,
235
+ password=SALESFORCE_PASSWORD,
236
+ security_token=SALESFORCE_SECURITY_TOKEN
237
+ )
238
+ motor_data = sf.apexecute("MotorDataAPI/", method="GET")
239
+ return motor_data # API returns the list of records
240
+ except Exception as e:
241
+ return f"Error pulling data from MotorDataAPI: {str(e)}"
242
+
243
+ # Function to format Salesforce data into a DataFrame with readable headers
244
+ def format_salesforce_data():
245
+ try:
246
+ data = pull_data_from_motor_api()
247
+ if isinstance(data, list):
248
+ df = pd.DataFrame(data)
249
+ df = df.rename(columns={
250
+ "Product_Name__c": "Product Name",
251
+ "Modal_Name__c": "Model Name",
252
+ "Current_Stocks__c": "Current Stocks"
253
+ })
254
+ # Remove unnecessary columns
255
+ df = df[["Product Name", "Model Name", "Current Stocks"]]
256
+ return df
257
  else:
258
+ return None
 
259
  except Exception as e:
260
+ return None
261
 
262
+ # Function to generate a bar graph from Salesforce data
263
+ def generate_bar_graph(df):
264
+ try:
265
+ fig, ax = plt.subplots(figsize=(12, 8))
266
+ df.plot(kind='bar', x="Product Name", y="Current Stocks", ax=ax, legend=False)
267
+ ax.set_title("Stock Distribution by Product Name")
268
+ ax.set_xlabel("Product Name")
269
+ ax.set_ylabel("Current Stocks")
270
+ plt.xticks(rotation=45, ha="right", fontsize=10)
271
+ plt.tight_layout()
272
+ buffer = BytesIO()
273
+ plt.savefig(buffer, format="png")
274
+ buffer.seek(0)
275
+ img = Image.open(buffer)
276
+ return img
277
+ except Exception as e:
278
+ return None
279
+
280
+ # Unified function to handle image processing and Salesforce interaction
281
  def process_image(image, mode, entry_type, quantity):
282
  extracted_text = extract_text(image)
283
+ if not extracted_text:
284
+ return "No text detected in the image.", None
285
+
286
+ product_name = match_product_name(extracted_text)
287
+ attributes = extract_attributes(extracted_text)
288
+ if product_name:
289
+ attributes["Product name"] = product_name
290
+
291
+ # Interact with Salesforce
292
  message = interact_with_salesforce(mode, entry_type, quantity, extracted_text)
 
293
 
294
+ numbered_output = "\n".join([f"{key}: {value}" for key, value in attributes.items()])
295
+ return f"Extracted Text:\n{extracted_text}\n\nAttributes and Values:\n{numbered_output}", message
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
296
 
297
+ # Gradio Interface
298
  def app():
299
+ df = format_salesforce_data()
300
+ table_component = None
301
+ bar_graph_component = None
302
+
303
+ if df is not None:
304
+ table_component = df.to_html(index=False)
305
+ bar_graph_image = generate_bar_graph(df)
306
+ if bar_graph_image:
307
+ bar_graph_component = bar_graph_image
308
+
309
+ return gr.TabbedInterface([
310
+ gr.Interface(
311
+ fn=process_image,
312
+ inputs=[
313
+ gr.Image(type="numpy", label="πŸ“„α΄œα΄˜ΚŸα΄α΄€α΄… Ιͺᴍᴀɒᴇ"),
314
+ gr.Dropdown(label="πŸ“ŒMode", choices=["ᴇɴᴛʀʏ", "ᴇxΙͺα΄›"], value="Entry"),
315
+ gr.Radio(label="πŸ“¦Entry Type", choices=["Sales", "Non-Sales"], value="Sales"),
316
+ gr.Number(label="πŸ”’Quantity", value=1, interactive=True),
317
+ ],
318
+ outputs=[
319
+ gr.Text(label="Ιͺᴍᴀɒᴇ α΄…α΄€α΄›α΄€ α΄ Ιͺᴇᴑᴇʀ"),
320
+ gr.Text(label="πŸ“οΌ²οΌ₯οΌ³οΌ΅οΌ¬οΌ΄")
321
+ ],
322
+ title="𝑽𝑬𝑡𝑲𝑨𝑻𝑨𝑹𝑨𝑴𝑨𝑡𝑨 𝑴𝑢𝑻𝑢𝑹𝑺",
323
+ description="πŸ“¦πˆππ•π„ππ“πŽπ‘π˜ πŒπ€ππ€π†π„πŒπ„ππ“"
324
+ ),
325
+ gr.Interface(
326
+ fn=lambda: (table_component, bar_graph_component),
327
+ inputs=[],
328
+ outputs=[
329
+ gr.HTML(label="Salesforce Data Table"),
330
+ gr.Image(type="pil", label="Stock Distribution Bar Graph")
331
+ ],
332
+ title="Salesforce Data",
333
+ description="View structured Salesforce data as a table and bar graph."
334
+ )
335
+ ], ["Processing", "Salesforce Data"])
336
+ # 🎨 Bright and Gradient UI with Updated Coloring
337
+ css = """
338
+ body {
339
+ background: linear-gradient(135deg, #282c34, #4b79a1);
340
+ font-family: 'Poppins', sans-serif;
341
+ }
342
+
343
+ .gradio-container {
344
+ border-radius: 20px;
345
+ padding: 30px;
346
+ background: rgba(255, 255, 255, 0.2);
347
+ backdrop-filter: blur(10px);
348
+ box-shadow: 0px 8px 30px rgba(0, 123, 255, 0.4);
349
+ border: 2px solid rgba(255, 255, 255, 0.4);
350
+ }
351
+
352
+ .gradio-title {
353
+ font-size: 48px;
354
+ font-weight: bold;
355
+ text-align: center;
356
+ background: linear-gradient(90deg, #ff7eb3, #ff758c);
357
+ -webkit-background-clip: text;
358
+ -webkit-text-fill-color: transparent;
359
+ text-shadow: 5px 5px 20px rgba(255, 105, 180, 0.6);
360
+ margin-bottom: 20px;
361
+ animation: glow 2s infinite alternate;
362
+ }
363
+
364
+ @keyframes glow {
365
+ from {
366
+ text-shadow: 5px 5px 30px rgba(255, 87, 134, 0.6);
367
+ }
368
+ to {
369
+ text-shadow: 6px 6px 40px rgba(255, 54, 90, 1);
370
+ }
371
+ }
372
+
373
+ .gradio-box {
374
+ border-radius: 15px;
375
+ padding: 25px;
376
+ background: linear-gradient(135deg, #6a11cb, #2575fc);
377
+ box-shadow: 0px 6px 25px rgba(30, 144, 255, 0.6);
378
+ border: 2px solid #6a5acd;
379
+ color: white;
380
+ font-size: 18px;
381
+ }
382
+
383
+ .gradio-button {
384
+ border-radius: 12px;
385
+ padding: 18px 36px;
386
+ font-size: 20px;
387
+ font-weight: bold;
388
+ color: #fff;
389
+ background: linear-gradient(135deg, #1e90ff, #00bfff);
390
+ box-shadow: 0px 6px 25px rgba(0, 191, 255, 0.6);
391
+ transition: all 0.3s ease-in-out;
392
+ }
393
+
394
+ .gradio-button:hover {
395
+ background: linear-gradient(135deg, #00bfff, #1e90ff);
396
+ box-shadow: 0px 10px 35px rgba(0, 191, 255, 0.9);
397
+ transform: scale(1.1);
398
+ }
399
+
400
+ .gradio-input {
401
+ border-radius: 10px;
402
+ padding: 16px;
403
+ font-size: 18px;
404
+ background: rgba(255, 255, 255, 0.3);
405
+ border: 2px solid rgba(0, 123, 255, 0.5);
406
+ color: #fff;
407
+ transition: 0.3s;
408
+ }
409
+
410
+ .gradio-input:focus {
411
+ border: 2px solid #1e90ff;
412
+ outline: none;
413
+ box-shadow: 0px 5px 20px rgba(30, 144, 255, 0.6);
414
+ }
415
+
416
+ .gradio-output {
417
+ background: linear-gradient(135deg, #f39c12, #e74c3c);
418
+ padding: 22px;
419
+ border-radius: 15px;
420
+ color: white;
421
+ font-size: 20px;
422
+ text-align: center;
423
+ border: 2px solid #f39c12;
424
+ }
425
+
426
+ .gradio-file {
427
+ background: linear-gradient(135deg, #8e44ad, #3498db);
428
+ color: white;
429
+ padding: 16px;
430
+ border-radius: 15px;
431
+ text-align: center;
432
+ font-size: 18px;
433
+ }
434
+ """
435
+
436
+
437
+
438
 
439
  if __name__ == "__main__":
440
+ app().launch(share=True)