Spaces:
Sleeping
Sleeping
USAMA BHATTI
commited on
Commit
Β·
3f23aac
1
Parent(s):
ba2fc46
Fix: Universal Port Configuration for Deployment
Browse files- Dockerfile +3 -2
- Procfile +1 -2
- backend/src/main.py +16 -12
- frontend/visual_search_test.html +32 -27
Dockerfile
CHANGED
|
@@ -34,5 +34,6 @@ ENV PYTHONPATH=/app:$PYTHONPATH
|
|
| 34 |
# 7. Expose Port
|
| 35 |
EXPOSE 8000
|
| 36 |
|
| 37 |
-
# 8. Run Command (
|
| 38 |
-
|
|
|
|
|
|
| 34 |
# 7. Expose Port
|
| 35 |
EXPOSE 8000
|
| 36 |
|
| 37 |
+
# 8. Run Command (Universal Logic)
|
| 38 |
+
# Yeh check karega: Agar server ne PORT diya hai to wo use karo, warna 8000 use karo.
|
| 39 |
+
CMD uvicorn backend.src.main:app --host 0.0.0.0 --port ${PORT:-8000}
|
Procfile
CHANGED
|
@@ -1,2 +1 @@
|
|
| 1 |
-
|
| 2 |
-
web: uvicorn backend.src.main:app --host 0.0.0.0 --port $PORT
|
|
|
|
| 1 |
+
web: uvicorn backend.src.main:app --host 0.0.0.0 --port $PORT
|
|
|
backend/src/main.py
CHANGED
|
@@ -2,14 +2,14 @@
|
|
| 2 |
# --- EXTERNAL IMPORTS ---
|
| 3 |
import os
|
| 4 |
import asyncio
|
| 5 |
-
import sys
|
| 6 |
from fastapi import FastAPI
|
| 7 |
-
from fastapi.staticfiles import StaticFiles
|
| 8 |
from fastapi.middleware.cors import CORSMiddleware
|
| 9 |
from backend.src.core.config import settings
|
| 10 |
-
|
| 11 |
# --- API Route Imports ---
|
| 12 |
-
from backend.src.api.routes import chat, ingestion, auth, settings as settings_route
|
| 13 |
|
| 14 |
# ==========================================
|
| 15 |
# π₯ WINDOWS FIX FOR DB TIMEOUTS π₯
|
|
@@ -25,21 +25,18 @@ app = FastAPI(
|
|
| 25 |
)
|
| 26 |
|
| 27 |
# 2. CORS Setup (Security)
|
| 28 |
-
# Frontend ko Backend se baat karne ki ijazat dena
|
| 29 |
app.add_middleware(
|
| 30 |
CORSMiddleware,
|
| 31 |
-
allow_origins=["*"],
|
| 32 |
allow_credentials=False,
|
| 33 |
allow_methods=["*"],
|
| 34 |
allow_headers=["*"],
|
| 35 |
)
|
| 36 |
|
| 37 |
-
# 3. Mount Static Files
|
| 38 |
-
# Ye check karta hai ke 'static' folder hai ya nahi, agar nahi to banata hai
|
| 39 |
if not os.path.exists("static"):
|
| 40 |
os.makedirs("static")
|
| 41 |
|
| 42 |
-
# Is line ka matlab hai: Jo bhi file 'static' folder mein hogi, wo '/static/filename' par milegi
|
| 43 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 44 |
|
| 45 |
# 4. Health Check Route
|
|
@@ -48,7 +45,7 @@ async def root():
|
|
| 48 |
return {
|
| 49 |
"message": "Welcome to OmniAgent Core π",
|
| 50 |
"status": "active",
|
| 51 |
-
"widget_url": "/static/widget.js"
|
| 52 |
}
|
| 53 |
|
| 54 |
# 5. API Router Includes
|
|
@@ -58,7 +55,14 @@ app.include_router(chat.router, prefix=settings.API_V1_STR, tags=["Chat"])
|
|
| 58 |
app.include_router(ingestion.router, prefix=settings.API_V1_STR, tags=["Ingestion"])
|
| 59 |
app.include_router(visual.router, prefix=settings.API_V1_STR, tags=["Visual Search"])
|
| 60 |
|
|
|
|
|
|
|
|
|
|
| 61 |
if __name__ == "__main__":
|
| 62 |
import uvicorn
|
| 63 |
-
#
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
# --- EXTERNAL IMPORTS ---
|
| 3 |
import os
|
| 4 |
import asyncio
|
| 5 |
+
import sys
|
| 6 |
from fastapi import FastAPI
|
| 7 |
+
from fastapi.staticfiles import StaticFiles
|
| 8 |
from fastapi.middleware.cors import CORSMiddleware
|
| 9 |
from backend.src.core.config import settings
|
| 10 |
+
|
| 11 |
# --- API Route Imports ---
|
| 12 |
+
from backend.src.api.routes import visual, chat, ingestion, auth, settings as settings_route
|
| 13 |
|
| 14 |
# ==========================================
|
| 15 |
# π₯ WINDOWS FIX FOR DB TIMEOUTS π₯
|
|
|
|
| 25 |
)
|
| 26 |
|
| 27 |
# 2. CORS Setup (Security)
|
|
|
|
| 28 |
app.add_middleware(
|
| 29 |
CORSMiddleware,
|
| 30 |
+
allow_origins=["*"],
|
| 31 |
allow_credentials=False,
|
| 32 |
allow_methods=["*"],
|
| 33 |
allow_headers=["*"],
|
| 34 |
)
|
| 35 |
|
| 36 |
+
# 3. Mount Static Files
|
|
|
|
| 37 |
if not os.path.exists("static"):
|
| 38 |
os.makedirs("static")
|
| 39 |
|
|
|
|
| 40 |
app.mount("/static", StaticFiles(directory="static"), name="static")
|
| 41 |
|
| 42 |
# 4. Health Check Route
|
|
|
|
| 45 |
return {
|
| 46 |
"message": "Welcome to OmniAgent Core π",
|
| 47 |
"status": "active",
|
| 48 |
+
"widget_url": "/static/widget.js"
|
| 49 |
}
|
| 50 |
|
| 51 |
# 5. API Router Includes
|
|
|
|
| 55 |
app.include_router(ingestion.router, prefix=settings.API_V1_STR, tags=["Ingestion"])
|
| 56 |
app.include_router(visual.router, prefix=settings.API_V1_STR, tags=["Visual Search"])
|
| 57 |
|
| 58 |
+
# ==========================================
|
| 59 |
+
# π₯ UNIVERSAL START LOGIC π₯
|
| 60 |
+
# ==========================================
|
| 61 |
if __name__ == "__main__":
|
| 62 |
import uvicorn
|
| 63 |
+
# Environment se PORT uthao, agar na mile to 8000 use karo
|
| 64 |
+
# Yeh logic Local + Deployment dono jagah chalegi
|
| 65 |
+
port = int(os.environ.get("PORT", 8000))
|
| 66 |
+
|
| 67 |
+
print(f"π Starting Server on Port: {port}")
|
| 68 |
+
uvicorn.run("backend.src.main:app", host="0.0.0.0", port=port, reload=True)
|
frontend/visual_search_test.html
CHANGED
|
@@ -3,32 +3,26 @@
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
-
<title>OmniAgent Visual Search Tester
|
| 7 |
<style>
|
| 8 |
-
body { font-family: 'Segoe UI',
|
| 9 |
.container { width: 100%; max-width: 900px; background: #fff; padding: 30px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); }
|
| 10 |
h1 { color: #2c3e50; text-align: center; margin-bottom: 10px; }
|
| 11 |
-
.subtitle { text-align: center; color: #7f8c8d; margin-bottom: 30px;
|
| 12 |
|
| 13 |
.input-group { display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; }
|
| 14 |
-
.input-group label { font-weight: bold;
|
| 15 |
.input-group input, .input-group button { padding: 12px; border-radius: 6px; border: 1px solid #ccc; font-size: 16px; }
|
| 16 |
|
| 17 |
-
.input-group button { background-color: #3498db; color: white; border: none; cursor: pointer;
|
| 18 |
-
.input-group button:hover { background-color: #2980b9; }
|
| 19 |
.input-group button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
|
| 20 |
|
| 21 |
-
#auth-status { text-align: center; padding: 15px; background: #f8f9fa; border-radius: 6px;
|
| 22 |
-
|
| 23 |
#search-results-container { margin-top: 30px; display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; }
|
| 24 |
-
|
| 25 |
-
.result-card {
|
| 26 |
-
.
|
| 27 |
-
.
|
| 28 |
-
.card-content { padding: 12px; text-align: center; }
|
| 29 |
-
.similarity-badge { background: #27ae60; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px; font-weight: bold; }
|
| 30 |
-
|
| 31 |
-
.info-message { grid-column: 1 / -1; text-align: center; font-size: 16px; color: #777; margin-top: 20px; }
|
| 32 |
.loader { border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 20px auto; display: none; }
|
| 33 |
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
| 34 |
</style>
|
|
@@ -36,33 +30,44 @@
|
|
| 36 |
<body>
|
| 37 |
<div class="container">
|
| 38 |
<h1>OmniAgent Visual Search</h1>
|
| 39 |
-
<p class="subtitle">
|
| 40 |
|
| 41 |
<div id="auth-status">
|
| 42 |
-
<p style="margin:0"><strong>Status:</strong> Waiting for
|
| 43 |
</div>
|
| 44 |
|
| 45 |
<div class="input-group">
|
| 46 |
-
|
| 47 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
|
| 49 |
-
<label for="image-upload-input">
|
| 50 |
<input type="file" id="image-upload-input" accept="image/*">
|
| 51 |
|
| 52 |
<button id="search-button" disabled>π Search Products</button>
|
| 53 |
</div>
|
| 54 |
|
| 55 |
<div id="loader" class="loader"></div>
|
| 56 |
-
<div id="search-results-container">
|
| 57 |
-
<p class="info-message">Results will appear here...</p>
|
| 58 |
-
</div>
|
| 59 |
</div>
|
| 60 |
|
| 61 |
<script src="visual_search_test.js"></script>
|
| 62 |
<script>
|
| 63 |
-
//
|
| 64 |
-
const
|
| 65 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
</script>
|
| 67 |
</body>
|
| 68 |
</html>
|
|
|
|
| 3 |
<head>
|
| 4 |
<meta charset="UTF-8">
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
+
<title>OmniAgent Visual Search Tester</title>
|
| 7 |
<style>
|
| 8 |
+
body { font-family: 'Segoe UI', sans-serif; background-color: #f4f7f9; color: #333; margin: 0; padding: 40px; display: flex; justify-content: center; }
|
| 9 |
.container { width: 100%; max-width: 900px; background: #fff; padding: 30px; border-radius: 12px; box-shadow: 0 10px 30px rgba(0,0,0,0.1); }
|
| 10 |
h1 { color: #2c3e50; text-align: center; margin-bottom: 10px; }
|
| 11 |
+
.subtitle { text-align: center; color: #7f8c8d; margin-bottom: 30px; }
|
| 12 |
|
| 13 |
.input-group { display: flex; flex-direction: column; gap: 15px; margin-bottom: 20px; }
|
| 14 |
+
.input-group label { font-weight: bold; font-size: 0.9em; color: #555; }
|
| 15 |
.input-group input, .input-group button { padding: 12px; border-radius: 6px; border: 1px solid #ccc; font-size: 16px; }
|
| 16 |
|
| 17 |
+
.input-group button { background-color: #3498db; color: white; border: none; cursor: pointer; font-weight: bold; }
|
|
|
|
| 18 |
.input-group button:disabled { background-color: #bdc3c7; cursor: not-allowed; }
|
| 19 |
|
| 20 |
+
#auth-status { text-align: center; padding: 15px; background: #f8f9fa; border-radius: 6px; border-left: 5px solid #bdc3c7; }
|
|
|
|
| 21 |
#search-results-container { margin-top: 30px; display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 20px; }
|
| 22 |
+
.result-card { background: #fff; border: 1px solid #eee; border-radius: 8px; overflow: hidden; }
|
| 23 |
+
.result-card img { width: 100%; height: 200px; object-fit: cover; }
|
| 24 |
+
.card-content { padding: 10px; text-align: center; }
|
| 25 |
+
.similarity-badge { background: #27ae60; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px; }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
.loader { border: 4px solid #f3f3f3; border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; margin: 20px auto; display: none; }
|
| 27 |
@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
|
| 28 |
</style>
|
|
|
|
| 30 |
<body>
|
| 31 |
<div class="container">
|
| 32 |
<h1>OmniAgent Visual Search</h1>
|
| 33 |
+
<p class="subtitle">Universal Tester (Local & Production)</p>
|
| 34 |
|
| 35 |
<div id="auth-status">
|
| 36 |
+
<p style="margin:0"><strong>Status:</strong> Waiting for inputs...</p>
|
| 37 |
</div>
|
| 38 |
|
| 39 |
<div class="input-group">
|
| 40 |
+
<!-- π₯ NEW: Dynamic URL Input -->
|
| 41 |
+
<label for="api-url-input">1. Backend URL (Local or Production)</label>
|
| 42 |
+
<input type="text" id="api-url-input" value="http://127.0.0.1:8000">
|
| 43 |
+
|
| 44 |
+
<label for="api-key-input">2. API Key</label>
|
| 45 |
+
<input type="text" id="api-key-input" placeholder="omni_...">
|
| 46 |
|
| 47 |
+
<label for="image-upload-input">3. Upload Image</label>
|
| 48 |
<input type="file" id="image-upload-input" accept="image/*">
|
| 49 |
|
| 50 |
<button id="search-button" disabled>π Search Products</button>
|
| 51 |
</div>
|
| 52 |
|
| 53 |
<div id="loader" class="loader"></div>
|
| 54 |
+
<div id="search-results-container"></div>
|
|
|
|
|
|
|
| 55 |
</div>
|
| 56 |
|
| 57 |
<script src="visual_search_test.js"></script>
|
| 58 |
<script>
|
| 59 |
+
// Init with value from input box
|
| 60 |
+
const urlInput = document.getElementById('api-url-input');
|
| 61 |
+
|
| 62 |
+
// Initial Init
|
| 63 |
+
VisualSearchTester.init(urlInput.value + "/api/v1/visual/search");
|
| 64 |
+
|
| 65 |
+
// Update init when URL changes
|
| 66 |
+
urlInput.addEventListener('input', function() {
|
| 67 |
+
// Remove trailing slash if user adds it
|
| 68 |
+
let cleanUrl = this.value.replace(/\/$/, "");
|
| 69 |
+
VisualSearchTester.init(cleanUrl + "/api/v1/visual/search");
|
| 70 |
+
});
|
| 71 |
</script>
|
| 72 |
</body>
|
| 73 |
</html>
|