JTh34 commited on
Commit
9b576e4
·
1 Parent(s): 1bf7896

🚀 Déploiement automatique RAG CHU 2025-06-30 17:06:09

Browse files
Files changed (3) hide show
  1. Dockerfile +31 -36
  2. backend/src/main.py +54 -41
  3. pyproject.toml +3 -1
Dockerfile CHANGED
@@ -1,58 +1,53 @@
1
  # Dockerfile pour le backend RAG CHU
2
  FROM python:3.11-slim
3
 
 
 
 
 
4
  # Variables d'environnement
5
- ENV PYTHONUNBUFFERED=1 \
6
- PYTHONDONTWRITEBYTECODE=1 \
7
- PIP_NO_CACHE_DIR=1 \
8
- PIP_DISABLE_PIP_VERSION_CHECK=1 \
9
- UV_NO_CACHE=1 \
10
- UV_PROJECT_ENVIRONMENT=/app/.venv
11
-
12
- # Installer les dépendances système
13
  RUN apt-get update && apt-get install -y \
14
  curl \
15
  build-essential \
16
- nodejs \
17
- npm \
 
 
 
18
  && rm -rf /var/lib/apt/lists/*
19
 
20
- # Installer uv
21
  RUN curl -LsSf https://astral.sh/uv/install.sh | sh
22
- ENV PATH="/root/.local/bin:$PATH"
23
 
24
- # Créer le répertoire de travail
25
  WORKDIR /app
26
 
27
- # Copier tout le backend en une fois
28
- COPY backend/ ./
29
-
30
- # Installer les dépendances Python
31
- RUN uv sync --frozen --no-dev && \
32
- chmod -R 777 .venv
33
-
34
- # Copier le frontend et le builder
35
- COPY frontend/ ./frontend/
36
 
37
- # Builder le frontend pendant le build Docker
38
- WORKDIR /app/frontend
39
- RUN npm install && npm run build
40
 
41
- # Se placer dans le répertoire backend pour l'exécution
42
- WORKDIR /app/backend
 
43
 
44
- # Créer les répertoires nécessaires et configurer les permissions
45
- RUN mkdir -p uploads static && \
46
- chmod 777 /tmp && \
47
- chmod -R 777 /app/.venv && \
48
- chmod -R 777 /app
49
 
50
  # Exposer le port
51
- EXPOSE 7860
52
 
53
  # Healthcheck
54
  HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
55
- CMD curl -f http://localhost:7860/api/health || exit 1
56
 
57
- # Commande de démarrage avec --no-cache
58
- CMD ["uv", "run", "--no-cache", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
  # Dockerfile pour le backend RAG CHU
2
  FROM python:3.11-slim
3
 
4
+ # Métadonnées
5
+ LABEL maintainer="CHU Developer <dev@chu.com>"
6
+ LABEL description="Backend RAG pour documents médicaux CHU"
7
+
8
  # Variables d'environnement
9
+ ENV PYTHONUNBUFFERED=1
10
+ ENV PYTHONDONTWRITEBYTECODE=1
11
+ ENV UV_CACHE_DIR=/tmp/uv-cache
12
+
13
+ # Installation des dépendances système
 
 
 
14
  RUN apt-get update && apt-get install -y \
15
  curl \
16
  build-essential \
17
+ libmagic1 \
18
+ poppler-utils \
19
+ tesseract-ocr \
20
+ tesseract-ocr-fra \
21
+ libreoffice \
22
  && rm -rf /var/lib/apt/lists/*
23
 
24
+ # Installation d'uv
25
  RUN curl -LsSf https://astral.sh/uv/install.sh | sh
26
+ ENV PATH="/root/.cargo/bin:$PATH"
27
 
28
+ # Répertoire de travail
29
  WORKDIR /app
30
 
31
+ # Copier les fichiers de configuration
32
+ COPY pyproject.toml uv.lock* ./
33
+ COPY backend/pyproject.toml backend/uv.lock* ./backend/
 
 
 
 
 
 
34
 
35
+ # Installation des dépendances
36
+ RUN uv sync --frozen
 
37
 
38
+ # Copier le code source
39
+ COPY backend/src ./backend/src
40
+ COPY backend/.env.example ./backend/.env.example
41
 
42
+ # Créer les répertoires nécessaires
43
+ RUN mkdir -p uploads backend/static
 
 
 
44
 
45
  # Exposer le port
46
+ EXPOSE 8000
47
 
48
  # Healthcheck
49
  HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
50
+ CMD curl -f http://localhost:8000/api/health || exit 1
51
 
52
+ # Point d'entrée
53
+ CMD ["uv", "run", "--directory", "backend", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
backend/src/main.py CHANGED
@@ -79,6 +79,17 @@ class ConnectionManager:
79
 
80
  manager = ConnectionManager()
81
 
 
 
 
 
 
 
 
 
 
 
 
82
  # Modèles Pydantic
83
  class ChatRequest(BaseModel):
84
  question: str
@@ -438,48 +449,50 @@ async def delete_document(document_id: str):
438
  logger.error(f"Erreur suppression document {document_id}: {e}")
439
  raise HTTPException(status_code=500, detail="Erreur lors de la suppression")
440
 
441
- # Route pour servir une interface simple (optionnel)
442
  @app.get("/")
443
- async def serve_index():
444
- """Page d'accueil simple"""
445
- return HTMLResponse("""
446
- <!DOCTYPE html>
447
- <html>
448
- <head>
449
- <title>RAG CHU - API Médicale</title>
450
- <style>
451
- body { font-family: Arial, sans-serif; margin: 40px; }
452
- .header { color: #2c3e50; }
453
- .endpoint { background: #f8f9fa; padding: 15px; margin: 10px 0; border-radius: 5px; }
454
- </style>
455
- </head>
456
- <body>
457
- <h1 class="header">🏥 RAG CHU - API Documents Médicaux</h1>
458
- <p>API pour l'analyse et la recherche dans les documents médicaux</p>
459
-
460
- <div class="endpoint">
461
- <h3>📖 Documentation Interactive</h3>
462
- <p><a href="/docs" target="_blank">Interface Swagger</a></p>
463
- </div>
464
-
465
- <div class="endpoint">
466
- <h3>🔍 Endpoints Principaux</h3>
467
- <ul>
468
- <li><code>POST /api/upload</code> - Upload document</li>
469
- <li><code>POST /api/analyze/{id}</code> - Analyser document</li>
470
- <li><code>POST /api/chat</code> - Chat avec RAG</li>
471
- <li><code>GET /api/documents</code> - Lister documents</li>
472
- <li><code>GET /api/health</code> - Statut API</li>
473
- </ul>
474
- </div>
475
-
476
- <div class="endpoint">
477
- <h3>📡 WebSocket</h3>
478
- <p><code>ws://localhost:8000/ws</code> - Notifications temps réel</p>
479
- </div>
480
- </body>
481
- </html>
482
- """)
 
 
483
 
484
  if __name__ == "__main__":
485
  import uvicorn
 
79
 
80
  manager = ConnectionManager()
81
 
82
+ # Configuration des fichiers statiques pour servir le frontend React
83
+ # Chemin vers le build du frontend (depuis le répertoire backend)
84
+ frontend_build_path = Path(__file__).parent.parent.parent / "frontend" / "build"
85
+
86
+ if frontend_build_path.exists():
87
+ # Servir les fichiers statiques du frontend
88
+ app.mount("/static", StaticFiles(directory=frontend_build_path / "static"), name="static")
89
+ logger.info(f"Frontend statique configuré: {frontend_build_path}")
90
+ else:
91
+ logger.warning(f"Répertoire frontend introuvable: {frontend_build_path}")
92
+
93
  # Modèles Pydantic
94
  class ChatRequest(BaseModel):
95
  question: str
 
449
  logger.error(f"Erreur suppression document {document_id}: {e}")
450
  raise HTTPException(status_code=500, detail="Erreur lors de la suppression")
451
 
452
+ # Routes pour servir le frontend React
453
  @app.get("/")
454
+ async def serve_react_app():
455
+ """Servir l'application React"""
456
+ index_path = frontend_build_path / "index.html"
457
+ if index_path.exists():
458
+ return HTMLResponse(content=index_path.read_text(), status_code=200)
459
+ else:
460
+ # Fallback si pas de frontend
461
+ return HTMLResponse("""
462
+ <!DOCTYPE html>
463
+ <html>
464
+ <head>
465
+ <title>RAG CHU - Erreur Frontend</title>
466
+ <style>
467
+ body { font-family: Arial, sans-serif; margin: 40px; background: #f8d7da; color: #721c24; }
468
+ .error { background: white; padding: 20px; border-radius: 8px; border-left: 4px solid #dc3545; }
469
+ </style>
470
+ </head>
471
+ <body>
472
+ <div class="error">
473
+ <h1> Frontend React non trouvé</h1>
474
+ <p>Le frontend n'a pas été correctement buildé.</p>
475
+ <p><strong>Chemin recherché:</strong> <code>{frontend_build_path}</code></p>
476
+ <p><a href="/docs">📖 Documentation API</a></p>
477
+ </div>
478
+ </body>
479
+ </html>
480
+ """)
481
+
482
+ # Catch-all pour les routes React (SPA routing)
483
+ @app.get("/{path:path}")
484
+ async def serve_spa(path: str):
485
+ """Servir l'application React pour toutes les routes non-API"""
486
+ # Exclure les routes API
487
+ if path.startswith("api/") or path.startswith("docs") or path.startswith("ws"):
488
+ raise HTTPException(status_code=404, detail="Route API non trouvée")
489
+
490
+ # Servir index.html pour toutes les autres routes (SPA routing)
491
+ index_path = frontend_build_path / "index.html"
492
+ if index_path.exists():
493
+ return HTMLResponse(content=index_path.read_text(), status_code=200)
494
+ else:
495
+ raise HTTPException(status_code=404, detail="Frontend non disponible")
496
 
497
  if __name__ == "__main__":
498
  import uvicorn
pyproject.toml CHANGED
@@ -2,7 +2,9 @@
2
  name = "backend"
3
  version = "0.1.0"
4
  description = "Backend RAG médical avec Qdrant et LangChain"
5
-
 
 
6
  requires-python = ">=3.9"
7
  dependencies = [
8
  # API Framework
 
2
  name = "backend"
3
  version = "0.1.0"
4
  description = "Backend RAG médical avec Qdrant et LangChain"
5
+ authors = [
6
+ { name = "CHU Developer", email = "dev@chu.com" }
7
+ ]
8
  requires-python = ">=3.9"
9
  dependencies = [
10
  # API Framework