haxerwddle commited on
Commit
8bd478d
·
1 Parent(s): 902a329

Private change

Browse files
Files changed (2) hide show
  1. app.py +68 -250
  2. requirements.txt +5 -2
app.py CHANGED
@@ -1,19 +1,37 @@
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,35 +40,39 @@ def classify_image(image):
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
- torch_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=60
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",
@@ -67,18 +89,18 @@ def explain_recycling(class_label):
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=60,
80
  do_sample=True,
81
- top_p = 0.9,
82
  temperature=0.3
83
  )
84
 
@@ -86,141 +108,38 @@ def explain_recycling(class_label):
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,120 +149,19 @@ def analyze_pipeline():
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)
 
 
 
 
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 (
11
  AutoTokenizer, AutoModelForCausalLM,
 
 
12
  pipeline
13
  )
14
+
15
+ # =========================
16
+ # FASTAPI APP
17
+ # =========================
18
+ app = FastAPI()
19
+
20
+ # =========================
21
+ # API MODELS
22
+ # =========================
23
+ class APIImage(BaseModel):
24
+ image_base64: str
25
+
26
+
27
+ # =========================
28
+ # LOAD CLASSIFIER
29
+ # =========================
30
  cls_model_name = "yangy50/garbage-classification"
31
  classifier = pipeline("image-classification", model=cls_model_name)
32
 
33
  def classify_image(image):
34
  preds = classifier(image)
 
35
  results = {}
36
  for item in preds[:3]:
37
  label = item["label"]
 
40
  return results
41
 
42
 
43
+ # =========================
44
+ # LOAD CHAT MODEL
45
+ # =========================
46
  tiny_model = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
47
 
48
  tokenizer = AutoTokenizer.from_pretrained(tiny_model)
49
  chat_model = AutoModelForCausalLM.from_pretrained(
50
  tiny_model,
51
+ torch_dtype=torch.bfloat16,
52
  device_map="auto",
53
+ low_cpu_mem_usage=True
54
+ )
55
 
56
  pipe = pipeline(
57
  "text-generation",
58
  model=chat_model,
59
  tokenizer=tokenizer,
60
  device_map="auto",
61
+ max_new_tokens=80
62
  )
63
 
 
64
 
65
+ def clean_chat_output(full_text):
66
  if "<|assistant|>" in full_text:
67
  full_text = full_text.split("<|assistant|>")[-1]
68
 
69
  lines = full_text.strip().split("\n")
70
+ if lines and lines[0].lower().startswith("item:"):
71
  lines = lines[1:]
72
 
73
  return "\n".join(lines).strip()
74
 
75
+
76
  def explain_recycling(class_label):
77
  system_msg = {
78
  "role": "system",
 
89
  "content": f"Item: {class_label}\nReturn the two bullet points now."
90
  }
91
  messages = [system_msg, user_msg]
92
+
93
  prompt = tokenizer.apply_chat_template(
94
+ messages,
95
+ tokenize=False,
96
  add_generation_prompt=True
97
  )
98
 
99
  outputs = pipe(
100
  prompt,
101
+ max_new_tokens=80,
102
  do_sample=True,
103
+ top_p=0.9,
104
  temperature=0.3
105
  )
106
 
 
108
  return clean_chat_output(raw)
109
 
110
 
111
+ # =========================
112
+ # WASTE ANALYSIS
113
+ # (your 3 versions)
114
+ # =========================
115
+ waste_analyzation = {...} # KEEP SAME CONTENTS
116
+ waste_analyzation_v2 = {...}
117
+ waste_analyzation_v3 = {...}
118
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  analysis = [waste_analyzation_v3, waste_analyzation_v2, waste_analyzation]
120
 
121
+ top_label = None
122
+
123
+
124
+ # =========================
125
+ # CLASSIFICATION PIPELINES
126
+ # =========================
127
  def classify_pipeline(image):
128
  global top_label
 
129
  predictions = classify_image(image)
130
+ top_label = max(predictions, key=predictions.get)
131
  return predictions
132
 
133
+
134
  def analyze_pipeline():
135
  global top_label
136
 
137
  if top_label is None:
138
  return "Please classify an image first."
139
+
 
 
140
  choice = random.randint(0, 2)
141
+ info = analysis[choice][top_label]
142
+
143
  result = (
144
  f"• Recycling type: {info['Recycling type']}\n"
145
  f"• Disposal: {info['Disposal']}\n"
 
149
  return result
150
 
151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
152
  # =========================
153
+ # API ENDPOINTS
154
  # =========================
155
+ @app.post("/api/classify")
156
+ def api_classify(data: APIImage):
157
+ img_bytes = base64.b64decode(data.image_base64)
158
+ image = Image.open(BytesIO(img_bytes)).convert("RGB")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ preds = classify_pipeline(image)
161
+ return {"predictions": preds}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
 
163
 
164
+ @app.post("/api/analyze")
165
+ def api_analyze():
166
+ result = analyze_pipeline()
167
+ return {"result": result}
requirements.txt CHANGED
@@ -1,8 +1,11 @@
1
- huggingface_hub
2
  gradio
3
  numpy
4
  Pillow
5
  torch
6
  transformers
7
  sentencepiece
8
- accelerate
 
 
 
 
 
 
1
  gradio
2
  numpy
3
  Pillow
4
  torch
5
  transformers
6
  sentencepiece
7
+ accelerate
8
+
9
+ fastapi
10
+ uvicorn
11
+ pydantic