Spaces:
Sleeping
Sleeping
Docker configs
Browse files- .github/workflows/huggingFace.yml +19 -0
- README.md +43 -6
- deploy.sh +55 -0
- docker-compose.prod.yml +48 -0
- frontend/src/pages/UploadPage/UploadPage.tsx +27 -25
- py_backend/.dockerignore +27 -0
- py_backend/Dockerfile +19 -0
- py_backend/app/config.py +9 -7
- py_backend/app/main.py +7 -3
- py_backend/app/routers/caption.py +14 -1
- py_backend/app/routers/upload.py +4 -0
- py_backend/requirements.txt +1 -0
.github/workflows/huggingFace.yml
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
name: Sync to Hugging Face hub
|
| 2 |
+
on:
|
| 3 |
+
push:
|
| 4 |
+
branches: [main]
|
| 5 |
+
workflow_dispatch:
|
| 6 |
+
|
| 7 |
+
jobs:
|
| 8 |
+
sync-to-hub:
|
| 9 |
+
runs-on: ubuntu-latest
|
| 10 |
+
steps:
|
| 11 |
+
- uses: actions/checkout@v3
|
| 12 |
+
with:
|
| 13 |
+
fetch-depth: 0
|
| 14 |
+
lfs: true
|
| 15 |
+
- name: Push to HF Space
|
| 16 |
+
env:
|
| 17 |
+
HF_API_KEY: ${{ secrets.HF_API_KEY }}
|
| 18 |
+
run: |
|
| 19 |
+
git push https://HF_USERNAME:${HF_API_KEY}@huggingface.co/spaces/SCGR/Promptaid_Vision main
|
README.md
CHANGED
|
@@ -1,8 +1,45 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
-
|
| 5 |
-
React => Python => postgreSQL => docker => fly.io/hugging face
|
| 6 |
|
| 7 |
-
|
| 8 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: PromptAid Vision
|
| 3 |
+
emoji: π
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 8080
|
| 8 |
+
---
|
| 9 |
|
| 10 |
+
# PromptAid Vision
|
|
|
|
| 11 |
|
| 12 |
+
AI-powered crisis map analysis platform using Vision Language Models.
|
| 13 |
+
|
| 14 |
+
## Features
|
| 15 |
+
|
| 16 |
+
- **Crisis map/drone imagery analysis**
|
| 17 |
+
- **Explore & export database**
|
| 18 |
+
- **Analytics dashboard**
|
| 19 |
+
|
| 20 |
+
## Tech Stack
|
| 21 |
+
|
| 22 |
+
- **Backend**: FastAPI, Python 3.11
|
| 23 |
+
- **AI Models**: OpenAI GPT-4V, Google Gemini, Hugging Face models
|
| 24 |
+
- **Database**: PostgreSQL
|
| 25 |
+
- **Storage**: S3-compatible storage
|
| 26 |
+
- **Frontend**: React with TypeScript
|
| 27 |
+
|
| 28 |
+
## Environment Variables
|
| 29 |
+
|
| 30 |
+
- `DATABASE_URL`: PostgreSQL connection string
|
| 31 |
+
- `S3_ENDPOINT`: S3-compatible storage endpoint
|
| 32 |
+
- `S3_ACCESS_KEY`: Storage access key
|
| 33 |
+
- `S3_SECRET_KEY`: Storage secret key
|
| 34 |
+
- `S3_BUCKET`: Storage bucket name
|
| 35 |
+
- `OPENAI_API_KEY`: OpenAI API key
|
| 36 |
+
- `GOOGLE_API_KEY`: Google API key
|
| 37 |
+
- `HF_API_KEY`: Hugging Face API key
|
| 38 |
+
|
| 39 |
+
## API Endpoints
|
| 40 |
+
|
| 41 |
+
- `/api/images` - Image management
|
| 42 |
+
- `/api/captions` - AI caption generation
|
| 43 |
+
- `/api/metadata` - Metadata operations
|
| 44 |
+
- `/api/models` - Available AI models
|
| 45 |
+
- `/api/contribute` - Contribution system
|
deploy.sh
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/bin/bash
|
| 2 |
+
|
| 3 |
+
echo "π PromptAid Vision Deployment Script"
|
| 4 |
+
echo "====================================="
|
| 5 |
+
|
| 6 |
+
echo "π¦ Building backend Docker image..."
|
| 7 |
+
cd py_backend
|
| 8 |
+
docker build -t promptaid-vision-backend .
|
| 9 |
+
|
| 10 |
+
if [ $? -eq 0 ]; then
|
| 11 |
+
echo "β
Backend image built successfully!"
|
| 12 |
+
else
|
| 13 |
+
echo "β Backend image build failed!"
|
| 14 |
+
exit 1
|
| 15 |
+
fi
|
| 16 |
+
|
| 17 |
+
cd ..
|
| 18 |
+
|
| 19 |
+
echo "π§ͺ Testing production setup locally..."
|
| 20 |
+
docker-compose -f docker-compose.prod.yml up -d
|
| 21 |
+
|
| 22 |
+
echo "β³ Waiting for services to start..."
|
| 23 |
+
sleep 10
|
| 24 |
+
|
| 25 |
+
echo "π Checking backend health..."
|
| 26 |
+
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/models)
|
| 27 |
+
|
| 28 |
+
if [ $response -eq 200 ]; then
|
| 29 |
+
echo "β
Backend is healthy and responding!"
|
| 30 |
+
else
|
| 31 |
+
echo "β Backend health check failed (HTTP $response)"
|
| 32 |
+
echo "π Stopping services..."
|
| 33 |
+
docker-compose -f docker-compose.prod.yml down
|
| 34 |
+
exit 1
|
| 35 |
+
fi
|
| 36 |
+
|
| 37 |
+
echo "π Stopping test services..."
|
| 38 |
+
docker-compose -f docker-compose.prod.yml down
|
| 39 |
+
|
| 40 |
+
echo ""
|
| 41 |
+
echo "π Deployment preparation completed!"
|
| 42 |
+
echo ""
|
| 43 |
+
echo "π Next steps:"
|
| 44 |
+
echo "1. Set up cloud database (PostgreSQL)"
|
| 45 |
+
echo "2. Set up cloud storage (S3-compatible)"
|
| 46 |
+
echo "3. Configure environment variables in Hugging Face Spaces"
|
| 47 |
+
echo "4. Push your code to Hugging Face Spaces"
|
| 48 |
+
echo ""
|
| 49 |
+
echo "π§ To test locally again, run:"
|
| 50 |
+
echo " docker-compose -f docker-compose.prod.yml up"
|
| 51 |
+
echo ""
|
| 52 |
+
echo "π To deploy to Hugging Face Spaces:"
|
| 53 |
+
echo " git add ."
|
| 54 |
+
echo " git commit -m 'Prepare for Hugging Face Spaces deployment'"
|
| 55 |
+
echo " git push"
|
docker-compose.prod.yml
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version: "3.8"
|
| 2 |
+
|
| 3 |
+
services:
|
| 4 |
+
backend:
|
| 5 |
+
build: ./py_backend
|
| 6 |
+
ports:
|
| 7 |
+
- "8080:8080"
|
| 8 |
+
environment:
|
| 9 |
+
- DATABASE_URL=postgresql://promptaid:promptaid@postgres:5432/promptaid
|
| 10 |
+
- S3_ENDPOINT=http://minio:9000
|
| 11 |
+
- S3_ACCESS_KEY=promptaid
|
| 12 |
+
- S3_SECRET_KEY=promptaid
|
| 13 |
+
- S3_BUCKET=promptaid
|
| 14 |
+
- ENVIRONMENT=production
|
| 15 |
+
- BASE_URL=http://localhost:8080
|
| 16 |
+
depends_on:
|
| 17 |
+
- postgres
|
| 18 |
+
- minio
|
| 19 |
+
restart: unless-stopped
|
| 20 |
+
|
| 21 |
+
postgres:
|
| 22 |
+
image: postgres:16
|
| 23 |
+
restart: always
|
| 24 |
+
environment:
|
| 25 |
+
POSTGRES_USER: promptaid
|
| 26 |
+
POSTGRES_PASSWORD: promptaid
|
| 27 |
+
POSTGRES_DB: promptaid
|
| 28 |
+
ports:
|
| 29 |
+
- "5433:5432"
|
| 30 |
+
volumes:
|
| 31 |
+
- pgdata:/var/lib/postgresql/data
|
| 32 |
+
|
| 33 |
+
minio:
|
| 34 |
+
image: minio/minio:latest
|
| 35 |
+
restart: always
|
| 36 |
+
command: server /data --console-address ":9001"
|
| 37 |
+
environment:
|
| 38 |
+
MINIO_ROOT_USER: promptaid
|
| 39 |
+
MINIO_ROOT_PASSWORD: promptaid
|
| 40 |
+
ports:
|
| 41 |
+
- "9000:9000"
|
| 42 |
+
- "9001:9001"
|
| 43 |
+
volumes:
|
| 44 |
+
- minio_data:/data
|
| 45 |
+
|
| 46 |
+
volumes:
|
| 47 |
+
pgdata:
|
| 48 |
+
minio_data:
|
frontend/src/pages/UploadPage/UploadPage.tsx
CHANGED
|
@@ -480,14 +480,15 @@ export default function UploadPage() {
|
|
| 480 |
|
| 481 |
return (
|
| 482 |
<PageContainer>
|
| 483 |
-
|
| 484 |
-
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
| 488 |
-
|
| 489 |
-
|
| 490 |
-
|
|
|
|
| 491 |
{/* Drop-zone */}
|
| 492 |
{step === 1 && !searchParams.get('step') && (
|
| 493 |
<div className="space-y-6">
|
|
@@ -829,22 +830,6 @@ export default function UploadPage() {
|
|
| 829 |
</div>
|
| 830 |
)}
|
| 831 |
|
| 832 |
-
{/* Success page */}
|
| 833 |
-
{step === 3 && (
|
| 834 |
-
<div className={styles.successContainer}>
|
| 835 |
-
<Heading level={2} className={styles.successHeading}>Saved!</Heading>
|
| 836 |
-
<p className={styles.successText}>Your caption has been successfully saved.</p>
|
| 837 |
-
<div className={styles.successButton}>
|
| 838 |
-
<Button
|
| 839 |
-
name="upload-another"
|
| 840 |
-
onClick={resetToStep1}
|
| 841 |
-
>
|
| 842 |
-
Upload Another
|
| 843 |
-
</Button>
|
| 844 |
-
</div>
|
| 845 |
-
</div>
|
| 846 |
-
)}
|
| 847 |
-
|
| 848 |
{/* Full Size Image Modal */}
|
| 849 |
{isFullSizeModalOpen && (
|
| 850 |
<div className={styles.fullSizeModalOverlay} onClick={() => setIsFullSizeModalOpen(false)}>
|
|
@@ -870,7 +855,24 @@ export default function UploadPage() {
|
|
| 870 |
)}
|
| 871 |
|
| 872 |
</div>
|
| 873 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 874 |
</PageContainer>
|
| 875 |
);
|
| 876 |
}
|
|
|
|
| 480 |
|
| 481 |
return (
|
| 482 |
<PageContainer>
|
| 483 |
+
{step !== 3 && (
|
| 484 |
+
<Container
|
| 485 |
+
heading="Upload Your Image"
|
| 486 |
+
headingLevel={2}
|
| 487 |
+
withHeaderBorder
|
| 488 |
+
withInternalPadding
|
| 489 |
+
className="max-w-7xl mx-auto"
|
| 490 |
+
>
|
| 491 |
+
<div className={styles.uploadContainer} data-step={step}>
|
| 492 |
{/* Drop-zone */}
|
| 493 |
{step === 1 && !searchParams.get('step') && (
|
| 494 |
<div className="space-y-6">
|
|
|
|
| 830 |
</div>
|
| 831 |
)}
|
| 832 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 833 |
{/* Full Size Image Modal */}
|
| 834 |
{isFullSizeModalOpen && (
|
| 835 |
<div className={styles.fullSizeModalOverlay} onClick={() => setIsFullSizeModalOpen(false)}>
|
|
|
|
| 855 |
)}
|
| 856 |
|
| 857 |
</div>
|
| 858 |
+
</Container>
|
| 859 |
+
)}
|
| 860 |
+
|
| 861 |
+
{/* Success page - outside the upload container */}
|
| 862 |
+
{step === 3 && (
|
| 863 |
+
<div className={styles.successContainer}>
|
| 864 |
+
<Heading level={2} className={styles.successHeading}>Saved!</Heading>
|
| 865 |
+
<p className={styles.successText}>Your caption has been successfully saved.</p>
|
| 866 |
+
<div className={styles.successButton}>
|
| 867 |
+
<Button
|
| 868 |
+
name="upload-another"
|
| 869 |
+
onClick={resetToStep1}
|
| 870 |
+
>
|
| 871 |
+
Upload Another
|
| 872 |
+
</Button>
|
| 873 |
+
</div>
|
| 874 |
+
</div>
|
| 875 |
+
)}
|
| 876 |
</PageContainer>
|
| 877 |
);
|
| 878 |
}
|
py_backend/.dockerignore
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__pycache__
|
| 2 |
+
*.pyc
|
| 3 |
+
*.pyo
|
| 4 |
+
*.pyd
|
| 5 |
+
.Python
|
| 6 |
+
env
|
| 7 |
+
pip-log.txt
|
| 8 |
+
pip-delete-this-directory.txt
|
| 9 |
+
.tox
|
| 10 |
+
.coverage
|
| 11 |
+
.coverage.*
|
| 12 |
+
.cache
|
| 13 |
+
nosetests.xml
|
| 14 |
+
coverage.xml
|
| 15 |
+
*.cover
|
| 16 |
+
*.log
|
| 17 |
+
.git
|
| 18 |
+
.mypy_cache
|
| 19 |
+
.pytest_cache
|
| 20 |
+
.hypothesis
|
| 21 |
+
.env
|
| 22 |
+
.venv
|
| 23 |
+
venv/
|
| 24 |
+
tests/
|
| 25 |
+
*.md
|
| 26 |
+
.gitignore
|
| 27 |
+
README.md
|
py_backend/Dockerfile
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
+
|
| 3 |
+
WORKDIR /app
|
| 4 |
+
|
| 5 |
+
RUN apt-get update && apt-get install -y \
|
| 6 |
+
gcc \
|
| 7 |
+
postgresql-client \
|
| 8 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
+
|
| 10 |
+
COPY requirements.txt .
|
| 11 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 12 |
+
|
| 13 |
+
COPY . .
|
| 14 |
+
|
| 15 |
+
RUN mkdir -p /app/logs
|
| 16 |
+
|
| 17 |
+
EXPOSE 8080
|
| 18 |
+
|
| 19 |
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]
|
py_backend/app/config.py
CHANGED
|
@@ -1,17 +1,19 @@
|
|
| 1 |
from pydantic_settings import BaseSettings
|
| 2 |
|
| 3 |
class Settings(BaseSettings):
|
| 4 |
-
DATABASE_URL: str
|
| 5 |
-
S3_ENDPOINT: str
|
| 6 |
-
S3_ACCESS_KEY: str
|
| 7 |
-
S3_SECRET_KEY: str
|
| 8 |
-
S3_BUCKET: str
|
| 9 |
-
|
| 10 |
OPENAI_API_KEY: str = ""
|
| 11 |
ANTHROPIC_API_KEY: str = ""
|
| 12 |
GOOGLE_API_KEY: str = ""
|
| 13 |
HF_API_KEY: str = ""
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
| 15 |
class Config:
|
| 16 |
env_file = ".env"
|
| 17 |
env_file_encoding = "utf-8-sig"
|
|
|
|
| 1 |
from pydantic_settings import BaseSettings
|
| 2 |
|
| 3 |
class Settings(BaseSettings):
|
| 4 |
+
DATABASE_URL: str = "postgresql://user:pass@host:5432/dbname"
|
| 5 |
+
S3_ENDPOINT: str = "https://your-s3-endpoint.com"
|
| 6 |
+
S3_ACCESS_KEY: str = ""
|
| 7 |
+
S3_SECRET_KEY: str = ""
|
| 8 |
+
S3_BUCKET: str = ""
|
|
|
|
| 9 |
OPENAI_API_KEY: str = ""
|
| 10 |
ANTHROPIC_API_KEY: str = ""
|
| 11 |
GOOGLE_API_KEY: str = ""
|
| 12 |
HF_API_KEY: str = ""
|
| 13 |
+
SPACE_ID: str = ""
|
| 14 |
+
ENVIRONMENT: str = "development"
|
| 15 |
+
BASE_URL: str = "http://localhost:8080"
|
| 16 |
+
|
| 17 |
class Config:
|
| 18 |
env_file = ".env"
|
| 19 |
env_file_encoding = "utf-8-sig"
|
py_backend/app/main.py
CHANGED
|
@@ -4,15 +4,17 @@ from app.routers import upload, caption, metadata, models
|
|
| 4 |
from app.config import settings
|
| 5 |
from app.routers.images import router as images_router
|
| 6 |
|
| 7 |
-
|
| 8 |
-
|
| 9 |
app = FastAPI(title="PromptAid Vision")
|
| 10 |
|
| 11 |
app.add_middleware(
|
| 12 |
CORSMiddleware,
|
| 13 |
allow_origins=[
|
| 14 |
"http://localhost:3000",
|
| 15 |
-
"http://localhost:5173"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
],
|
| 17 |
allow_credentials=True,
|
| 18 |
allow_methods=["*"],
|
|
@@ -27,6 +29,8 @@ app.include_router(images_router, prefix="/api/contribute", tags=["contribute"]
|
|
| 27 |
|
| 28 |
print("π PromptAid Vision API server ready")
|
| 29 |
print("π Available endpoints: /api/images, /api/captions, /api/metadata, /api/models")
|
|
|
|
|
|
|
| 30 |
|
| 31 |
|
| 32 |
|
|
|
|
| 4 |
from app.config import settings
|
| 5 |
from app.routers.images import router as images_router
|
| 6 |
|
|
|
|
|
|
|
| 7 |
app = FastAPI(title="PromptAid Vision")
|
| 8 |
|
| 9 |
app.add_middleware(
|
| 10 |
CORSMiddleware,
|
| 11 |
allow_origins=[
|
| 12 |
"http://localhost:3000",
|
| 13 |
+
"http://localhost:5173",
|
| 14 |
+
"https://huggingface.co",
|
| 15 |
+
"https://*.hf.space",
|
| 16 |
+
"https://*.hf.space",
|
| 17 |
+
"*"
|
| 18 |
],
|
| 19 |
allow_credentials=True,
|
| 20 |
allow_methods=["*"],
|
|
|
|
| 29 |
|
| 30 |
print("π PromptAid Vision API server ready")
|
| 31 |
print("π Available endpoints: /api/images, /api/captions, /api/metadata, /api/models")
|
| 32 |
+
print(f"π Environment: {settings.ENVIRONMENT}")
|
| 33 |
+
print("π CORS enabled for Hugging Face Spaces")
|
| 34 |
|
| 35 |
|
| 36 |
|
py_backend/app/routers/caption.py
CHANGED
|
@@ -3,12 +3,12 @@ from sqlalchemy.orm import Session
|
|
| 3 |
from typing import List
|
| 4 |
from .. import crud, database, schemas, storage
|
| 5 |
from ..services.vlm_service import vlm_manager
|
|
|
|
| 6 |
|
| 7 |
from ..services.stub_vlm_service import StubVLMService
|
| 8 |
from ..services.gpt4v_service import GPT4VService
|
| 9 |
from ..services.gemini_service import GeminiService
|
| 10 |
from ..services.huggingface_service import LLaVAService, BLIP2Service, InstructBLIPService
|
| 11 |
-
from ..config import settings
|
| 12 |
|
| 13 |
stub_service = StubVLMService()
|
| 14 |
vlm_manager.register_service(stub_service)
|
|
@@ -129,6 +129,9 @@ async def create_caption(
|
|
| 129 |
except Exception:
|
| 130 |
url = f"/api/images/{c.image_id}/file"
|
| 131 |
|
|
|
|
|
|
|
|
|
|
| 132 |
img_dict = convert_image_to_dict(c, url)
|
| 133 |
return schemas.ImageOut(**img_dict)
|
| 134 |
|
|
@@ -152,6 +155,10 @@ def get_caption(
|
|
| 152 |
except Exception:
|
| 153 |
url = f"/api/images/{caption.image_id}/file"
|
| 154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
img_dict = convert_image_to_dict(caption, url)
|
| 156 |
return schemas.ImageOut(**img_dict)
|
| 157 |
|
|
@@ -176,6 +183,9 @@ def get_captions_by_image(
|
|
| 176 |
except Exception:
|
| 177 |
url = f"/api/images/{caption.image_id}/file"
|
| 178 |
|
|
|
|
|
|
|
|
|
|
| 179 |
img_dict = convert_image_to_dict(caption, url)
|
| 180 |
result.append(schemas.ImageOut(**img_dict))
|
| 181 |
|
|
@@ -232,6 +242,9 @@ def update_caption(
|
|
| 232 |
except Exception:
|
| 233 |
url = f"/api/images/{caption.image_id}/file"
|
| 234 |
|
|
|
|
|
|
|
|
|
|
| 235 |
img_dict = convert_image_to_dict(caption, url)
|
| 236 |
return schemas.ImageOut(**img_dict)
|
| 237 |
|
|
|
|
| 3 |
from typing import List
|
| 4 |
from .. import crud, database, schemas, storage
|
| 5 |
from ..services.vlm_service import vlm_manager
|
| 6 |
+
from ..config import settings
|
| 7 |
|
| 8 |
from ..services.stub_vlm_service import StubVLMService
|
| 9 |
from ..services.gpt4v_service import GPT4VService
|
| 10 |
from ..services.gemini_service import GeminiService
|
| 11 |
from ..services.huggingface_service import LLaVAService, BLIP2Service, InstructBLIPService
|
|
|
|
| 12 |
|
| 13 |
stub_service = StubVLMService()
|
| 14 |
vlm_manager.register_service(stub_service)
|
|
|
|
| 129 |
except Exception:
|
| 130 |
url = f"/api/images/{c.image_id}/file"
|
| 131 |
|
| 132 |
+
if url and url.startswith('/'):
|
| 133 |
+
url = f"{settings.BASE_URL}{url}"
|
| 134 |
+
|
| 135 |
img_dict = convert_image_to_dict(c, url)
|
| 136 |
return schemas.ImageOut(**img_dict)
|
| 137 |
|
|
|
|
| 155 |
except Exception:
|
| 156 |
url = f"/api/images/{caption.image_id}/file"
|
| 157 |
|
| 158 |
+
|
| 159 |
+
if url and url.startswith('/'):
|
| 160 |
+
url = f"{settings.BASE_URL}{url}"
|
| 161 |
+
|
| 162 |
img_dict = convert_image_to_dict(caption, url)
|
| 163 |
return schemas.ImageOut(**img_dict)
|
| 164 |
|
|
|
|
| 183 |
except Exception:
|
| 184 |
url = f"/api/images/{caption.image_id}/file"
|
| 185 |
|
| 186 |
+
if url and url.startswith('/'):
|
| 187 |
+
url = f"{settings.BASE_URL}{url}"
|
| 188 |
+
|
| 189 |
img_dict = convert_image_to_dict(caption, url)
|
| 190 |
result.append(schemas.ImageOut(**img_dict))
|
| 191 |
|
|
|
|
| 242 |
except Exception:
|
| 243 |
url = f"/api/images/{caption.image_id}/file"
|
| 244 |
|
| 245 |
+
if url and url.startswith('/'):
|
| 246 |
+
url = f"{settings.BASE_URL}{url}"
|
| 247 |
+
|
| 248 |
img_dict = convert_image_to_dict(caption, url)
|
| 249 |
return schemas.ImageOut(**img_dict)
|
| 250 |
|
py_backend/app/routers/upload.py
CHANGED
|
@@ -3,6 +3,7 @@ from pydantic import BaseModel
|
|
| 3 |
import io
|
| 4 |
from sqlalchemy.orm import Session
|
| 5 |
from .. import crud, schemas, storage, database
|
|
|
|
| 6 |
from typing import List
|
| 7 |
import boto3
|
| 8 |
import time
|
|
@@ -35,6 +36,9 @@ def convert_image_to_dict(img, image_url):
|
|
| 35 |
print(f"Warning: Error processing countries for image {img.image_id}: {e}")
|
| 36 |
countries_list = []
|
| 37 |
|
|
|
|
|
|
|
|
|
|
| 38 |
img_dict = {
|
| 39 |
"image_id": img.image_id,
|
| 40 |
"file_key": img.file_key,
|
|
|
|
| 3 |
import io
|
| 4 |
from sqlalchemy.orm import Session
|
| 5 |
from .. import crud, schemas, storage, database
|
| 6 |
+
from ..config import settings
|
| 7 |
from typing import List
|
| 8 |
import boto3
|
| 9 |
import time
|
|
|
|
| 36 |
print(f"Warning: Error processing countries for image {img.image_id}: {e}")
|
| 37 |
countries_list = []
|
| 38 |
|
| 39 |
+
if image_url and image_url.startswith('/'):
|
| 40 |
+
image_url = f"{settings.BASE_URL}{image_url}"
|
| 41 |
+
|
| 42 |
img_dict = {
|
| 43 |
"image_id": img.image_id,
|
| 44 |
"file_key": img.file_key,
|
py_backend/requirements.txt
CHANGED
|
@@ -19,3 +19,4 @@ httpx
|
|
| 19 |
requests
|
| 20 |
pycountry>=22.3.5
|
| 21 |
pycountry-convert>=0.7.2
|
|
|
|
|
|
| 19 |
requests
|
| 20 |
pycountry>=22.3.5
|
| 21 |
pycountry-convert>=0.7.2
|
| 22 |
+
python-multipart
|