haxerwddle commited on
Commit
b1cdb15
·
1 Parent(s): 5091547

Reverting

Browse files
Files changed (3) hide show
  1. app.py +293 -72
  2. requirements.txt +0 -3
  3. spaces.yaml +0 -3
app.py CHANGED
@@ -1,34 +1,19 @@
1
- import base64
2
- from io import BytesIO
3
- from PIL import Image
4
-
5
- from fastapi import FastAPI
6
- from pydantic import BaseModel
7
-
8
  import random
9
  import torch
10
- from transformers import T5Tokenizer, T5ForConditionalGeneration, pipeline
11
-
12
- # =========================
13
- # FASTAPI APP
14
- # =========================
15
- app = FastAPI()
16
-
17
- # =========================
18
- # API MODELS
19
- # =========================
20
- class APIImage(BaseModel):
21
- image_base64: str
22
-
23
-
24
- # =========================
25
- # LOAD CLASSIFIER
26
- # =========================
27
  cls_model_name = "yangy50/garbage-classification"
28
  classifier = pipeline("image-classification", model=cls_model_name)
29
 
30
  def classify_image(image):
31
  preds = classifier(image)
 
32
  results = {}
33
  for item in preds[:3]:
34
  label = item["label"]
@@ -37,70 +22,205 @@ def classify_image(image):
37
  return results
38
 
39
 
40
- # ------------------ LOAD CHAT MODEL
41
- tiny_model = "google/flan-t5-small"
42
 
43
- # tokenizer + model
44
- tokenizer = T5Tokenizer.from_pretrained(tiny_model)
45
- chat_model = T5ForConditionalGeneration.from_pretrained(tiny_model)
 
 
 
46
 
47
- # Use text2text-generation for T5-style models
48
  pipe = pipeline(
49
- task="text2text-generation",
50
  model=chat_model,
51
  tokenizer=tokenizer,
52
- device=-1, # -1 = CPU (safe)
53
  max_new_tokens=80
54
  )
55
 
 
 
 
 
 
 
 
 
 
 
 
56
  def explain_recycling(class_label):
57
- # Construct a simple single-string prompt for T5
58
- prompt = (
59
- "You are an expert in waste sorting. "
60
- "Always answer using exactly two bullet points:\n"
61
- " Recycling type: <Item category>\n"
62
- "• Disposal: <clear, detailed correct sentence>\n"
63
- f"Item: {class_label}\n"
64
- "Return the two bullet points now."
 
 
 
 
 
 
 
 
 
 
 
 
65
  )
66
 
67
- outputs = pipe(prompt, max_new_tokens=80, do_sample=False)
68
- # outputs is a list of dicts: [{"generated_text": "..."}]
69
- text = outputs[0].get("generated_text", "").strip()
70
- return text
71
-
 
 
72
 
73
- # =========================
74
- # WASTE ANALYSIS
75
- # =========================
76
- waste_analyzation = {...} # KEEP SAME CONTENTS
77
- waste_analyzation_v2 = {...}
78
- waste_analyzation_v3 = {...}
79
 
80
- analysis = [waste_analyzation_v3, waste_analyzation_v2, waste_analyzation]
81
 
 
82
  top_label = None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
-
85
- # =========================
86
- # CLASSIFICATION PIPELINES
87
- # =========================
88
  def classify_pipeline(image):
89
  global top_label
 
90
  predictions = classify_image(image)
91
- top_label = max(predictions, key=predictions.get)
92
  return predictions
93
 
94
-
95
  def analyze_pipeline():
96
  global top_label
97
 
98
  if top_label is None:
99
  return "Please classify an image first."
100
-
 
 
101
  choice = random.randint(0, 2)
102
- info = analysis[choice][top_label]
103
-
104
  result = (
105
  f"• Recycling type: {info['Recycling type']}\n"
106
  f"• Disposal: {info['Disposal']}\n"
@@ -110,19 +230,120 @@ def analyze_pipeline():
110
  return result
111
 
112
 
 
113
  # =========================
114
- # API ENDPOINTS
115
  # =========================
116
- @app.post("/api/classify")
117
- def api_classify(data: APIImage):
118
- img_bytes = base64.b64decode(data.image_base64)
119
- image = Image.open(BytesIO(img_bytes)).convert("RGB")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
 
121
- preds = classify_pipeline(image)
122
- return {"predictions": preds}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
 
125
- @app.post("/api/analyze")
126
- def api_analyze():
127
- result = analyze_pipeline()
128
- return {"result": result}
 
1
+ import gradio as gr
 
 
 
 
 
 
2
  import random
3
  import torch
4
+ from transformers import (
5
+ AutoTokenizer, AutoModelForCausalLM,
6
+ T5Tokenizer,
7
+ T5ForConditionalGeneration,
8
+ pipeline
9
+ )
10
+ # ------------------ LOAD CLASSIFIER ------------------
 
 
 
 
 
 
 
 
 
 
11
  cls_model_name = "yangy50/garbage-classification"
12
  classifier = pipeline("image-classification", model=cls_model_name)
13
 
14
  def classify_image(image):
15
  preds = classifier(image)
16
+
17
  results = {}
18
  for item in preds[:3]:
19
  label = item["label"]
 
22
  return results
23
 
24
 
25
+ # ------------------ LOAD CHAT MODEL ------------------
26
+ tiny_model = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
27
 
28
+ tokenizer = AutoTokenizer.from_pretrained(tiny_model)
29
+ chat_model = AutoModelForCausalLM.from_pretrained(
30
+ tiny_model,
31
+ dtype=torch.bfloat16,
32
+ device_map="auto",
33
+ low_cpu_mem_usage=True)
34
 
 
35
  pipe = pipeline(
36
+ "text-generation",
37
  model=chat_model,
38
  tokenizer=tokenizer,
39
+ device_map="auto",
40
  max_new_tokens=80
41
  )
42
 
43
+ def clean_chat_output(full_text):
44
+
45
+ if "<|assistant|>" in full_text:
46
+ full_text = full_text.split("<|assistant|>")[-1]
47
+
48
+ lines = full_text.strip().split("\n")
49
+ if lines[0].lower().startswith("item:"):
50
+ lines = lines[1:]
51
+
52
+ return "\n".join(lines).strip()
53
+
54
  def explain_recycling(class_label):
55
+ system_msg = {
56
+ "role": "system",
57
+ "content": (
58
+ "You are an expert in waste sorting. "
59
+ "You ALWAYS answer using exactly two bullet points:\n"
60
+ "• Recycling type: <Item category>\n"
61
+ "• Disposal: <clear, detailed correct sentence>\n"
62
+ "No extra text, no introductions, no explanations."
63
+ )
64
+ }
65
+ user_msg = {
66
+ "role": "user",
67
+ "content": f"Item: {class_label}\nReturn the two bullet points now."
68
+ }
69
+ messages = [system_msg, user_msg]
70
+
71
+ prompt = tokenizer.apply_chat_template(
72
+ messages,
73
+ tokenize=False,
74
+ add_generation_prompt=True
75
  )
76
 
77
+ outputs = pipe(
78
+ prompt,
79
+ max_new_tokens=80,
80
+ do_sample=True,
81
+ top_p = 0.9,
82
+ temperature=0.3
83
+ )
84
 
85
+ raw = outputs[0]["generated_text"]
86
+ return clean_chat_output(raw)
 
 
 
 
87
 
 
88
 
89
+ # ------------------ PIPELINE ------------------
90
  top_label = None
91
+ waste_analyzation = {
92
+ "cardboard": {
93
+ "Recycling type": "Paper/Cardboard recycling",
94
+ "Disposal": "Flatten the cardboard boxes and remove any non-paper packing materials before placing them in the recycling bin.",
95
+ "Tips": "Keep cardboard dry and clean to ensure it can be recycled efficiently.",
96
+ "Extra": "Avoid using waxed or heavily coated cardboard, as it may not be recyclable."
97
+ },
98
+ "glass": {
99
+ "Recycling type": "Glass recycling",
100
+ "Disposal": "Rinse glass bottles and jars, remove lids, and place them in a dedicated glass recycling container.",
101
+ "Tips": "Avoid breaking the glass; broken pieces can be hazardous and may complicate processing.",
102
+ "Extra": "Colored glass is often recycled separately; check local recycling rules."
103
+ },
104
+ "metal": {
105
+ "Recycling type": "Metal recycling",
106
+ "Disposal": "Rinse aluminum cans and steel containers, remove labels if possible, and put them in the metal recycling bin.",
107
+ "Tips": "Crush cans to save space and facilitate transport.",
108
+ "Extra": "Avoid contaminating with food waste to improve recycling efficiency."
109
+ },
110
+ "paper": {
111
+ "Recycling type": "Paper recycling",
112
+ "Disposal": "Sort newspapers, office paper, and magazines into the paper recycling bin; remove plastic coatings and staples.",
113
+ "Tips": "Shred sensitive documents but keep shredded paper in a bag to avoid scattering.",
114
+ "Extra": "Do not recycle wet or food-stained paper."
115
+ },
116
+ "plastic": {
117
+ "Recycling type": "Plastic recycling",
118
+ "Disposal": "Rinse plastic bottles, containers, and packaging, and place them in the plastic recycling bin.",
119
+ "Tips": "Check recycling codes; some plastics (like #3 PVC) are not widely recyclable.",
120
+ "Extra": "Remove caps and labels when possible to improve sorting efficiency."
121
+ },
122
+ "trash": {
123
+ "Recycling type": "General waste / landfill",
124
+ "Disposal": "Place non-recyclable items in the regular trash bin; avoid mixing with recyclables.",
125
+ "Tips": "Separate hazardous materials like batteries, electronics, or chemicals for special disposal.",
126
+ "Extra": "Try to reduce overall waste by reusing and composting when possible."
127
+ }
128
+ }
129
+ waste_analyzation_v2 = {
130
+ "cardboard": {
131
+ "Recycling type": "Paper/Cardboard recycling",
132
+ "Disposal": "Fold or cut cardboard into smaller flat pieces so it fits properly in recycling bins.",
133
+ "Tips": "Keep cardboard free from oils or food stains to avoid contaminating the batch.",
134
+ "Extra": "Cardboard with shiny or laminated surfaces may need separate processing."
135
+ },
136
+ "glass": {
137
+ "Recycling type": "Glass recycling",
138
+ "Disposal": "Remove lids and caps, lightly rinse, and place glass containers into the glass-only bin.",
139
+ "Tips": "Do not place broken drinking glasses or ceramics with recyclable glass—they melt at different temperatures.",
140
+ "Extra": "Some regions require taking glass to drop-off centers instead of curbside bins."
141
+ },
142
+ "metal": {
143
+ "Recycling type": "Metal recycling",
144
+ "Disposal": "Empty metal containers and place them in the metal bin; labels may stay on.",
145
+ "Tips": "Keep metal separate from electronics or batteries, which require special facilities.",
146
+ "Extra": "Large metal objects like appliances may require bulk recycling pickup."
147
+ },
148
+ "paper": {
149
+ "Recycling type": "Paper recycling",
150
+ "Disposal": "Place clean, dry paper products such as envelopes and notebooks into paper bins.",
151
+ "Tips": "Do not recycle coated paper (e.g., laminated or plastic-lined pages).",
152
+ "Extra": "Paper with heavy ink coverage might be processed separately."
153
+ },
154
+ "plastic": {
155
+ "Recycling type": "Plastic recycling",
156
+ "Disposal": "Clean and drain plastic bottles or tubs, then place them in the plastics bin.",
157
+ "Tips": "Flatten plastic bottles to reduce volume unless your local guidelines say otherwise.",
158
+ "Extra": "Some plastics like polystyrene foam require special drop-off locations."
159
+ },
160
+ "trash": {
161
+ "Recycling type": "General waste / landfill",
162
+ "Disposal": "Dispose of unrecyclable materials in regular waste; secure loose items in bags.",
163
+ "Tips": "Separate hazardous or toxic waste like paint, solvents, or chemicals.",
164
+ "Extra": "Reduce landfill impact by choosing reusable products whenever possible."
165
+ }
166
+ }
167
+ waste_analyzation_v3 = {
168
+ "cardboard": {
169
+ "Recycling type": "Paper/Cardboard recycling",
170
+ "Disposal": "Remove packing tape when possible and place cardboard in dry storage until pickup day.",
171
+ "Tips": "Avoid leaving cardboard outdoors where rain could weaken fibers and ruin recyclability.",
172
+ "Extra": "Food-contaminated cardboard can often be composted instead of recycled."
173
+ },
174
+ "glass": {
175
+ "Recycling type": "Glass recycling",
176
+ "Disposal": "Sort by color only if required locally; rinse lightly and drop into the proper bin.",
177
+ "Tips": "Handle carefully to avoid breakage, as shattered glass is often not recyclable in curbside programs.",
178
+ "Extra": "Glass jars with metal clasps or rubber seals may need partial disassembly before recycling."
179
+ },
180
+ "metal": {
181
+ "Recycling type": "Metal recycling",
182
+ "Disposal": "Ensure metal food cans are clean and empty before placing in the recycling bin.",
183
+ "Tips": "Rinse cans briefly—no need for perfect cleaning—as this prevents pests and odors.",
184
+ "Extra": "Metal lids from jars should be recycled separately from the glass container."
185
+ },
186
+ "paper": {
187
+ "Recycling type": "Paper recycling",
188
+ "Disposal": "Place paper in the appropriate bin; keep shredded paper in a paper bag if accepted.",
189
+ "Tips": "Avoid mixing paper with wet waste like food scraps to maintain recyclability.",
190
+ "Extra": "Sticky notes and small scraps may or may not be accepted depending on the facility."
191
+ },
192
+ "plastic": {
193
+ "Recycling type": "Plastic recycling",
194
+ "Disposal": "Recycle only plastics accepted by your local program; rinse and drain them completely.",
195
+ "Tips": "Avoid recycling small plastic pieces under 2 inches—they may jam sorting machinery.",
196
+ "Extra": "Hard-to-recycle plastics may be collected through special community programs."
197
+ },
198
+ "trash": {
199
+ "Recycling type": "General waste / landfill",
200
+ "Disposal": "Place all non-recyclables in the trash bin; tie bags securely to avoid leakage.",
201
+ "Tips": "Do not place batteries, electronics, or sharp objects directly into household trash.",
202
+ "Extra": "Consider composting organic waste to reduce household trash volume."
203
+ }
204
+ }
205
+ analysis = [waste_analyzation_v3, waste_analyzation_v2, waste_analyzation]
206
 
 
 
 
 
207
  def classify_pipeline(image):
208
  global top_label
209
+
210
  predictions = classify_image(image)
211
+ top_label = max(predictions, key=predictions.get) # top-1
212
  return predictions
213
 
 
214
  def analyze_pipeline():
215
  global top_label
216
 
217
  if top_label is None:
218
  return "Please classify an image first."
219
+
220
+ explanation = explain_recycling(top_label)
221
+
222
  choice = random.randint(0, 2)
223
+ info = analysis[choice][top_label]
 
224
  result = (
225
  f"• Recycling type: {info['Recycling type']}\n"
226
  f"• Disposal: {info['Disposal']}\n"
 
230
  return result
231
 
232
 
233
+ # ------------------ GRADIO UI ------------------
234
  # =========================
235
+ # CSS
236
  # =========================
237
+ custom_css = """
238
+
239
+
240
+ #main-title {
241
+ text-align: center;
242
+ color: #2E7D32;
243
+ font-size: 34px;
244
+ font-weight: 800;
245
+ margin-bottom: 22px;
246
+ }
247
+
248
+ .gradio-container {
249
+ background: linear-gradient(135deg, #E8F5E9 0%, #F1F8E9 100%);
250
+ font-family: 'Segoe UI', sans-serif;
251
+ }
252
+
253
+ #explainbox textarea {
254
+ background: #ffffff;
255
+ height: 120px;
256
+ border: 2px solid #A5D6A7;
257
+ border-radius: 12px;
258
+ padding: 12px;
259
+ font-size: 15px;
260
+ }
261
 
262
+ .gr-button.primary {
263
+ background: #43A047 !important;
264
+ color: white !important;
265
+ border-radius: 12px !important;
266
+ padding: 12px 20px !important;
267
+ font-size: 17px !important;
268
+ box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.15);
269
+ transition: 0.2s ease;
270
+ }
271
+
272
+ textarea, .gr-textbox textarea, #explainbox textarea {
273
+ color: #1B5E20 !important;
274
+ }
275
+
276
+ #tips-box li {
277
+ color: #2E7D32 !important;
278
+ }
279
+
280
+ .gr-button.primary:hover {
281
+ background: #2E7D32 !important;
282
+ transform: translateY(-2px);
283
+ }
284
+
285
+
286
+ """
287
+
288
+ # =========================
289
+ # GRADIO UI
290
+ # =========================
291
+ with gr.Blocks() as demo:
292
+
293
+ # TITLE
294
+ gr.Markdown("<h1 id='main-title'>♻️ AI Waste Classifier</h1>")
295
+
296
+ # INPUT ROW
297
+ with gr.Row():
298
+ with gr.Column(scale=1):
299
+ img_input = gr.Image(
300
+ type="pil",
301
+ label="📸 Upload waste image",
302
+ elem_id="upload-area"
303
+ )
304
+
305
+ with gr.Column(scale=1):
306
+ gr.Markdown(
307
+ """
308
+ <div id="tips-box" style="border:2px solid #A5D6A7; padding:16px; border-radius:14px; background:white;">
309
+ <h3 style="color:#2E7D32;">🌍 Quick recycling tips:</h3>
310
+ <ul>
311
+ <li>Organic waste → green bin</li>
312
+ <li>Plastic, metal waste → recycle</li>
313
+ <li>Wash your glass waste!</li>
314
+ <li>Battery, eletrical devices → non-metal container</li>
315
+ </ul>
316
+ </div>
317
+ """
318
+ )
319
+
320
+ # OUTPUTS
321
+ cls_output = gr.Label(
322
+ num_top_classes=3,
323
+ label="🔍 Classifier Prediction (Top 3)"
324
+ )
325
+ analyze_btn = gr.Button("Classify Waste", variant="primary")
326
+
327
+ analyze_btn.click(
328
+ classify_pipeline,
329
+ inputs=img_input,
330
+ outputs=cls_output
331
+ )
332
+
333
+ explain_output = gr.Textbox(
334
+ label="🧩 Detailed Recycling & Disposal Advice",
335
+ elem_id="explainbox",
336
+ lines=6
337
+ )
338
+
339
+ # BUTTON
340
+ analyze_result_btn = gr.Button("Analyze", variant="primary")
341
+
342
+ analyze_result_btn.click(
343
+ analyze_pipeline,
344
+ inputs=None,
345
+ outputs=explain_output
346
+ )
347
 
348
 
349
+ demo.launch(css=custom_css)
 
 
 
requirements.txt CHANGED
@@ -6,6 +6,3 @@ transformers
6
  sentencepiece
7
  accelerate
8
 
9
- fastapi
10
- uvicorn
11
- pydantic
 
6
  sentencepiece
7
  accelerate
8
 
 
 
 
spaces.yaml DELETED
@@ -1,3 +0,0 @@
1
- sdk: "python"
2
- python_version: "3.10"
3
- app_file: "app.py"