-
Notifications
You must be signed in to change notification settings - Fork 29
Decouple AI services using dependency injection #126
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?
Conversation
…services Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
fixingbharat | b3d086f | Jan 09 2026, 05:12 PM |
…rvices Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
Co-authored-by: RohanExploit <178623867+RohanExploit@users.noreply.github.com>
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
This pull request successfully decouples AI services from the main application by introducing a comprehensive dependency injection pattern. The refactoring addresses the tight coupling issue identified in issue #73, making the codebase more testable, maintainable, and flexible.
Changes:
- Introduced protocol-based service interfaces and dependency injection container for 8 AI services (3 existing + 5 detection services)
- Created concrete implementations for HuggingFace-based detection services and mock implementations for testing
- Extended factory pattern to support environment-based service provider selection
- Refactored main application to use dependency injection instead of direct service imports
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| backend/ai_interfaces.py | Added DetectionService protocol and extended AIServiceContainer to manage 8 service instances with proper initialization |
| backend/ai_factory.py | Extended factory with detection service creation functions and updated create_all_ai_services to return 8-tuple |
| backend/main.py | Removed direct imports of detection modules and refactored all endpoints to use injected services via get_ai_services() |
| backend/hf_detection_services.py | Created concrete implementations wrapping HuggingFace CLIP models and local detection models with Protocol compliance |
| backend/mock_detection_services.py | Implemented test doubles for all 5 detection services with predictable mock responses |
| backend/test_comprehensive_ai_services.py | Added comprehensive test suite covering all 8 services in mock mode |
| SECURITY_SUMMARY.md | Documented security analysis showing 0 vulnerabilities and approval for production |
| REFACTORING_SUMMARY.md | Detailed implementation summary with benefits, metrics, and usage examples |
| FINAL_VERIFICATION.md | Complete verification checklist confirming all objectives met with test results |
| AI_SERVICE_DECOUPLING.md | Architecture documentation explaining the solution, benefits, and migration path |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| from pothole_detection import detect_potholes | ||
| import asyncio | ||
| # Run blocking detection in threadpool | ||
| return await asyncio.to_thread(detect_potholes, image) | ||
|
|
||
|
|
||
| class GarbageDetectionService(DetectionService): | ||
| """Local model-based garbage detection service.""" | ||
|
|
||
| async def detect(self, image: Image.Image, client: Any = None) -> List[Dict[str, Any]]: | ||
| """Detect garbage using local detection model.""" | ||
| from garbage_detection import detect_garbage | ||
| import asyncio | ||
| # Run blocking detection in threadpool | ||
| return await asyncio.to_thread(detect_garbage, image) |
Copilot
AI
Jan 14, 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 asyncio module is imported inside the detect method on lines 45 and 56, but asyncio.to_thread is only available in Python 3.9+. While this is generally acceptable, consider importing asyncio at the module level to make the dependency explicit and improve clarity. The current implementation works but having local imports inside methods can reduce code readability.
The main application directly imported and instantiated AI service providers (
hf_service,ai_service), creating tight coupling that prevented service substitution and testing isolation.Changes
Service Abstraction Layer
ai_interfaces.py: AddedDetectionServiceprotocol for image-based detection services (vandalism, infrastructure, flooding, pothole, garbage)AIServiceContainer: Now manages 8 service instances (3 existing AI services + 5 detection services)ProtocoltypeService Implementations
hf_detection_services.py: Concrete implementations wrapping HuggingFace and local detection modelsmock_detection_services.py: Test doubles returning predictable responses for unit testingFactory Pattern
ai_factory.py: Added factory functions for all detection servicesAI_SERVICE_TYPEenv var (gemini/mock)create_all_ai_services()returns all 8 services as tupleMain Application Refactor
main.py:get_ai_services()instead of direct function callsUsage
Production (default):
Testing:
Adding providers:
Services can now be swapped without touching application code. Test coverage includes mock implementations for all 8 services.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.