-
Notifications
You must be signed in to change notification settings - Fork 30
Add Waste Sorter, Optimize for Render/Netlify, & Restore Pothole Detection via HF #320
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add Waste Sorter, Optimize for Render/Netlify, & Restore Pothole Detection via HF #320
Conversation
…e Detection via HF - Enabled `waste` route in `frontend/src/App.jsx`. - Removed heavy ML dependencies (`torch`, `ultralytics`, `opencv-python-headless`) from `backend/requirements.txt` to support free tier deployment. - Modified `backend/pothole_detection.py` to gracefully handle missing `ultralyticsplus` and added `is_model_available()` check. - Updated `backend/main.py` to fallback to Hugging Face CLIP API (`detect_pothole_clip`) when local pothole model is unavailable. - Added `detect_pothole_clip` to `backend/hf_api_service.py`. - Fixed duplicate `React` import in `frontend/src/App.jsx`. - Verified frontend functionality via Playwright script. - Verified backend startup via `pytest`. Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
❌ Deploy Preview for fixmybharat failed. Why did it fail? →
|
🙏 Thank you for your contribution, @RohanExploit!PR Details:
Quality Checklist:
Review Process:
Note: The maintainers will monitor code quality and ensure the overall project flow isn't broken. |
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📝 WalkthroughWalkthroughAdds a pothole CLIP-based detector and a graceful fallback for pothole detection when the local ML model is unavailable; removes local ML deps from backend requirements; refactors pothole model loading/availability; and updates frontend routing and detector composition. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Endpoint as Pothole Endpoint
participant AvailCheck as Model Availability
participant LocalModel as Local ML Model
participant HFAPI as HF CLIP API
Client->>Endpoint: POST /detect/pothole (image)
Endpoint->>AvailCheck: is_model_available()?
alt Model Available
AvailCheck-->>Endpoint: True
Endpoint->>LocalModel: detect_potholes(image) (threadpool)
LocalModel-->>Endpoint: detections
else Model Unavailable
AvailCheck-->>Endpoint: False
Endpoint-->>Endpoint: log fallback
Endpoint->>HFAPI: detect_pothole_clip(image) (async)
HFAPI-->>Endpoint: detections
end
Endpoint-->>Client: JSON response (detections)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/App.jsx (1)
618-628:⚠️ Potential issue | 🟠 MajorMissing
onBackprop passed to detector components.The detector components expect an
onBackprop (as shown inFireDetector,BlockedRoadDetector,StrayAnimalDetector,WasteDetector, etc.), but<Component />at line 624 doesn't receive it. This will cause the internal back button in each detector to be non-functional.🐛 Proposed fix to pass onBack to detector components
{Object.entries(DETECTORS).map(([path, Component]) => ( <Route key={path} path={`/${path}`} element={ <DetectorWrapper onBack={() => navigate('/home')} title={path.replace('-', ' ')}> - <Component /> + <Component onBack={() => navigate('/home')} /> </DetectorWrapper> } /> ))}
🤖 Fix all issues with AI agents
In `@backend/pothole_detection.py`:
- Around line 160-162: The current early return "if model is None: return []" in
backend/pothole_detection.py conflates "model unavailable" with "no detections";
replace that empty-list return with raising a specific sentinel exception (e.g.,
ModelLoadException) so callers can distinguish failures from valid empty
results, and add/declare the ModelLoadException class (or reuse an existing
error type) and update the function docstring/signature where this check occurs
to document the raised exception so callers can catch it and respond (e.g.,
return 503).
🧹 Nitpick comments (3)
frontend/src/App.jsx (1)
10-10:Landingcomponent is imported but not used in any route.The
Landingview is lazy-loaded but there's no corresponding<Route>that renders it. Additionally, the root path/has no explicit route, so visitors will seeNotFound. If this is intentional, consider removing the unused import; otherwise, add a route for/.💡 Option: Add a landing route or remove unused import
If Landing should be the homepage:
<Routes> + <Route path="/" element={<Landing setView={navigateToView} />} /> {/* Main Views */} <Route path="/home" element={Or if it's not needed, remove the import:
-const Landing = React.lazy(() => import('./views/Landing'));frontend_log.txt (1)
6-36: Consider excluding dev server logs from version control.This appears to be transient runtime output; keeping it in the repo adds noise and can leak local timing details. Prefer removing it and ignoring via .gitignore or keeping it as a CI artifact instead.
backend/pothole_detection.py (1)
17-25: Cache the dependency check to avoid repeated ImportError overhead.
is_model_available()can be called per request; when the dependency is absent, the repeated ImportError cost is avoidable. Memoizing keeps the hot path cheap.♻️ Proposed change (memoize availability)
+from functools import lru_cache @@ -def is_model_available(): +@lru_cache(maxsize=1) +def is_model_available():
| if model is None: | ||
| return [] | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Return value masks “model unavailable” vs “no detections.”
An empty list is also a valid “no potholes” result, so callers can’t distinguish a load failure. Consider raising ModelLoadException (or another sentinel) so the caller can fall back or surface a 503.
🐛 Suggested change to surface model-unavailable explicitly
- if model is None:
- return []
+ if model is None:
+ raise ModelLoadException(
+ "keremberke/yolov8n-pothole-segmentation",
+ details={"error": "model unavailable"}
+ )
@@
- except Exception as e:
+ except ModelLoadException:
+ raise
+ except Exception as e:🤖 Prompt for AI Agents
In `@backend/pothole_detection.py` around lines 160 - 162, The current early
return "if model is None: return []" in backend/pothole_detection.py conflates
"model unavailable" with "no detections"; replace that empty-list return with
raising a specific sentinel exception (e.g., ModelLoadException) so callers can
distinguish failures from valid empty results, and add/declare the
ModelLoadException class (or reuse an existing error type) and update the
function docstring/signature where this check occurs to document the raised
exception so callers can catch it and respond (e.g., return 503).
- Added `frontend/public/_redirects` to handle SPA routing (rewrite /* to /index.html). - Added `frontend/public/_headers` to enforce security headers (X-Frame-Options, etc.). - Verified that these files are copied to the build output (`dist/`) during `npm run build`, fixing the "Redirect rules" and "Header rules" CI failures. Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds the missing Waste Sorter route/UI wiring while making backend pothole detection resilient in lightweight deploys by removing heavy local ML dependencies and introducing a Hugging Face API fallback path.
Changes:
- Frontend: refactors
App.jsxlazy-loading and addswasteto the detector routing map. - Backend: removes heavyweight local ML packages from
requirements.txtand introduces an HF-based pothole detector (detect_pothole_clip). - Backend: updates pothole detection to be import-safe when optional ML deps are missing and adds fallback logic in the pothole endpoint.
Reviewed changes
Copilot reviewed 8 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend_log.txt | Updates local Vite run log output (non-functional change). |
| frontend/src/App.jsx | Consolidates imports/lazy-loading, adds waste detector route via DETECTORS, and adjusts app component structure. |
| frontend/package-lock.json | Lockfile updates from dependency resolution/metadata changes. |
| backend/requirements.txt | Removes heavy local ML deps to reduce slug size and memory footprint. |
| backend/pothole_detection.py | Makes pothole detection import-safe and changes model-load behavior. |
| backend/main.py | Adds conditional local-vs-HF execution path for pothole detection endpoint. |
| backend/hf_api_service.py | Adds detect_pothole_clip using the HF CLIP API helper. |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if is_model_available(): | ||
| # Use local model if available (blocking) | ||
| detections = await run_in_threadpool(detect_potholes, pil_image) | ||
| else: | ||
| # Fallback to Hugging Face API | ||
| logger.info("Local pothole model unavailable, falling back to HF API") | ||
| client = request.app.state.http_client | ||
| detections = await detect_pothole_clip(pil_image, client=client) |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
detect_pothole_endpoint decides between local vs HF using is_model_available(), but that only checks whether ultralyticsplus can be imported. If the import succeeds but load_model() returns None (e.g., model download fails or other runtime error), this endpoint will still choose the local path and return empty detections instead of falling back to HF. Consider basing the decision on whether the model actually loaded (e.g., call get_model() once at startup / cache a readiness flag) or catch a local-model failure and then invoke detect_pothole_clip as fallback.
| except Exception as e: | ||
| logger.error(f"Failed to load model: {e}") | ||
| raise ModelLoadException("keremberke/yolov8n-pothole-segmentation", details={"error": str(e)}) from e | ||
| return None |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
load_model() swallows all non-ImportError exceptions and returns None. This causes get_model() to treat initialization as successful and cache a None model, making subsequent detections silently return [] with no error signal for callers to trigger a fallback. Consider re-raising (or wrapping in ModelLoadException) for unexpected load failures so callers can distinguish “model unavailable” from “no potholes found.”
| return None | |
| raise |
| try: | ||
| model = get_model() | ||
| if model is None: | ||
| return [] |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning an empty list when model is None makes a model-load/config problem indistinguishable from a real “no detections” result. If the API is expected to fall back to HF when the local model can’t run, consider raising a dedicated exception here (or in get_model()) so callers can reliably detect and handle the failure mode.
| return [] | |
| logger.error("Pothole detection model is not available (get_model() returned None).") | |
| raise DetectionException( | |
| "Pothole detection model is not available", | |
| "pothole", | |
| details={"error": "model_unavailable"} | |
| ) |
| fetchRecentIssues(); | ||
| }, [fetchRecentIssues]); | ||
|
|
||
| // Determine if current route is a detector | ||
| const isDetectorRoute = useMemo(() => { | ||
| const currentPath = location.pathname.split('/')[1]; | ||
| return Object.keys(DETECTORS).includes(currentPath); | ||
| }, [location.pathname]); | ||
|
|
||
|
|
||
| // Check if we're on the landing page | ||
| const isLandingPage = location.pathname === '/'; | ||
|
|
||
| // If on landing page, render it without the main layout | ||
| if (isLandingPage) { | ||
| return ( | ||
| <Suspense fallback={ | ||
| <div className="flex items-center justify-center min-h-screen bg-gradient-to-br from-gray-50 to-blue-50"> | ||
| <LoadingSpinner size="xl" variant="primary" /> | ||
| </div> | ||
| }> | ||
| <Landing /> | ||
| </Suspense> | ||
| ); | ||
| } | ||
|
|
||
| // Otherwise render the main app layout | ||
| return ( | ||
| optimize-lazy-loading-313 | ||
| <div className="min-h-screen bg-gray-50 text-gray-800 font-sans"> | ||
| <Suspense fallback={<Loader />}><ChatWidget /></Suspense> | ||
|
|
||
| <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 min-h-screen flex flex-col"> | ||
| <header className="text-center mb-8 pb-6 border-b border-gray-200"> | ||
| <h1 className="text-4xl font-extrabold text-transparent bg-clip-text bg-gradient-to-r from-orange-600 to-blue-600 tracking-tight"> | ||
| VishwaGuru | ||
| </h1> | ||
| <p className="text-gray-500 font-medium mt-2">Empowering Citizens, Solving Problems.</p> | ||
| </header> | ||
|
|
||
| <main className="flex-grow w-full max-w-5xl mx-auto bg-white shadow-xl rounded-2xl p-6 sm:p-8 border border-gray-100"> | ||
| {loading && <Loader />} | ||
| {error && <div className="bg-red-50 text-red-600 p-3 rounded-lg text-sm text-center my-4">{error}</div>} | ||
|
|
||
| <Suspense fallback={<Loader />}> | ||
| <Routes> | ||
| <Route path="/" element={<Home setView={navigateToView} fetchResponsibilityMap={fetchResponsibilityMap} recentIssues={recentIssues} handleUpvote={handleUpvote}/>} /> | ||
| <Route path="/map" element={<MapView responsibilityMap={responsibilityMap} setView={navigateToView}/>} /> | ||
| <Route path="/report" element={<ReportForm setView={navigateToView} setLoading={setLoading} setError={setError} setActionPlan={setActionPlan} loading={loading}/>} /> | ||
| <Route path="/action" element={<ActionView actionPlan={actionPlan} setActionPlan={setActionPlan} setView={navigateToView}/>} /> | ||
| <Route path="/mh-rep" element={<MaharashtraRepView setView={navigateToView} setLoading={setLoading} setError={setError} setMaharashtraRepInfo={setMaharashtraRepInfo} maharashtraRepInfo={maharashtraRepInfo} loading={loading}/>} /> | ||
|
|
||
| <Route path="/pothole" element={<PotholeDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/garbage" element={<GarbageDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/vandalism" element={<VandalismDetector />} /> | ||
| <Route path="/flood" element={<FloodDetector />} /> | ||
| <Route path="/infrastructure" element={<InfrastructureDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/parking" element={<IllegalParkingDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/streetlight" element={<StreetLightDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/fire" element={<FireDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/animal" element={<StrayAnimalDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/blocked" element={<BlockedRoadDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/tree" element={<TreeDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/pest" element={<PestDetector onBack={() => navigate('/')}/>} /> | ||
| <Route path="/smart-scan" element={<SmartScanner onBack={() => navigate('/')}/>} /> | ||
| <Route path="*" element={<NotFound />} /> | ||
| </Routes> | ||
| </Suspense> | ||
| </main> | ||
|
|
||
| <footer className="mt-8 text-center text-gray-400 text-sm pb-8"> | ||
| © {new Date().getFullYear()} VishwaGuru. All rights reserved. | ||
| </footer> | ||
|
|
||
| <div className="min-h-screen bg-gradient-to-br from-gray-50 via-blue-50/30 to-gray-100 text-gray-900 font-sans overflow-hidden"> | ||
| {/* Animated background elements */} | ||
| <div className="fixed inset-0 z-0 pointer-events-none"> |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The router no longer defines a route for /, and Landing is lazily imported but never rendered. With the Netlify SPA redirect (/* -> /index.html), users hitting the site root will end up on the * route and see NotFound. Add an explicit / route (render Landing or redirect to /home).
| optimize-lazy-loading-313 | ||
| import React, { useState, useEffect, Suspense } from 'react'; | ||
| import { BrowserRouter as Router, Routes, Route, useNavigate } from 'react-router-dom'; | ||
| import React, { useState, useEffect, Suspense, useCallback, useMemo } from 'react'; |
Copilot
AI
Feb 2, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused import useMemo.
| import React, { useState, useEffect, Suspense, useCallback, useMemo } from 'react'; | |
| import React, { useState, useEffect, Suspense, useCallback } from 'react'; |
- Updated `netlify.toml` to use `base = "frontend"` to ensure correct build context. - Removed redundant inline `[[redirects]]` and `[[headers]]` from `netlify.toml` in favor of static files. - Restored `frontend/public/_redirects` and `frontend/public/_headers` to ensure they are copied to the publish directory (`dist`). - Verified `frontend/src/App.jsx` integrity. Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
🔍 Quality Reminder |
- Updated `netlify.toml` to use explicit root-relative commands (`npm install --prefix frontend && npm run build --prefix frontend`) to avoid `base` directory ambiguity. - Restored `frontend/public/_redirects` and `frontend/public/_headers` to ensure proper routing and security on Netlify. - Removed heavy ML dependencies (`torch`, `ultralytics`) from `backend/requirements.txt` to enable deployment on Render free tier. - Implemented graceful fallback to Hugging Face API for pothole detection when local models are unavailable. - Cleaned up `frontend/src/App.jsx` to remove artifacts and fix routing. Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
This PR addresses the user's request to add visible UI features, ensure deployability on Netlify/Render, and optimize resource usage.
Key Changes:
'waste'route tofrontend/src/App.jsxto enable the "Waste Sorter" feature.Reactimports inApp.jsx.torch,ultralytics,transformers, andopencv-python-headlessfrombackend/requirements.txtto significantly reduce slug size and memory usage, making it suitable for Render's free tier.backend/pothole_detection.pyto be import-safe when ML libraries are missing.detect_pothole_clipinbackend/hf_api_service.pyusing the Hugging Face API.backend/main.pyto automatically fallback to the HF API for pothole detection if the local model cannot be loaded, ensuring the feature remains functional even in lightweight environments.PR created automatically by Jules for task 12249067456740966540 started by @RohanExploit
Summary by CodeRabbit
New Features
Improvements
Chores