chore(ci): ajout workflow publish + nettoyage services + conf hosts
Some checks failed
publish-images / docker-build-and-push (push) Failing after 23s
Some checks failed
publish-images / docker-build-and-push (push) Failing after 23s
This commit is contained in:
parent
fddfa6f7bf
commit
f50481cc38
64
.gitea/workflows/publish.yml
Normal file
64
.gitea/workflows/publish.yml
Normal file
@ -0,0 +1,64 @@
|
||||
name: publish-images
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev, main ]
|
||||
tags: [ 'v*' ]
|
||||
|
||||
env:
|
||||
REGISTRY: git.4nkweb.com
|
||||
IMAGE_OWNER: 4nk
|
||||
IMAGE_REPO: 4NK_IA_back
|
||||
|
||||
jobs:
|
||||
docker-build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.USER }}
|
||||
password: ${{ secrets.TOKEN }}
|
||||
|
||||
- name: Compute tags
|
||||
id: meta
|
||||
run: |
|
||||
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
|
||||
VERSION_TAG="${GITHUB_REF_NAME}"
|
||||
else
|
||||
SHORT_SHA=$(echo "${GITHUB_SHA}" | cut -c1-8)
|
||||
VERSION_TAG="sha-${SHORT_SHA}"
|
||||
fi
|
||||
echo "version=${VERSION_TAG}" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Build & Push host-api
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ./docker/host-api
|
||||
file: ./docker/host-api/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_REPO }}/host-api:${{ steps.meta.outputs.version }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_REPO }}/host-api:latest
|
||||
|
||||
- name: Build & Push worker
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./docker/worker/Dockerfile
|
||||
push: true
|
||||
platforms: linux/amd64
|
||||
tags: |
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_REPO }}/worker:${{ steps.meta.outputs.version }}
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_OWNER }}/${{ env.IMAGE_REPO }}/worker:latest
|
@ -1,67 +0,0 @@
|
||||
SHELL := /bin/bash
|
||||
ENV ?= infra/.env
|
||||
|
||||
# Charger les variables d'environnement
|
||||
include $(ENV)
|
||||
export
|
||||
|
||||
.PHONY: help up down start-simple logs ps clean restart
|
||||
|
||||
help: ## Afficher l'aide
|
||||
@echo "Commandes disponibles :"
|
||||
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
up: ## Démarrer tous les services (version complète)
|
||||
cd infra && docker compose up -d
|
||||
|
||||
up-simple: ## Démarrer les services simplifiés (sans IA)
|
||||
cd infra && docker compose -f docker-compose.simple.yml up -d
|
||||
|
||||
down: ## Arrêter tous les services
|
||||
cd infra && docker compose down
|
||||
|
||||
down-simple: ## Arrêter les services simplifiés
|
||||
cd infra && docker compose -f docker-compose.simple.yml down
|
||||
|
||||
start-simple: ## Initialiser l'infrastructure simplifiée
|
||||
bash ops/start-simple.sh
|
||||
|
||||
logs: ## Afficher les logs
|
||||
cd infra && docker compose logs -f --tail=200
|
||||
|
||||
logs-simple: ## Afficher les logs (version simplifiée)
|
||||
cd infra && docker compose -f docker-compose.simple.yml logs -f --tail=200
|
||||
|
||||
ps: ## Afficher le statut des services
|
||||
cd infra && docker compose ps
|
||||
|
||||
ps-simple: ## Afficher le statut des services (version simplifiée)
|
||||
cd infra && docker compose -f docker-compose.simple.yml ps
|
||||
|
||||
clean: ## Nettoyer les volumes et images
|
||||
cd infra && docker compose down -v
|
||||
docker system prune -f
|
||||
|
||||
restart: ## Redémarrer tous les services
|
||||
cd infra && docker compose restart
|
||||
|
||||
build: ## Reconstruire les images
|
||||
cd infra && docker compose build --no-cache
|
||||
|
||||
build-simple: ## Reconstruire les images (version simplifiée)
|
||||
cd infra && docker compose -f docker-compose.simple.yml build --no-cache
|
||||
|
||||
test-api: ## Tester l'API
|
||||
curl -F "file=@tests/data/sample.pdf" \
|
||||
-F "id_dossier=D-2025-001" \
|
||||
-F "source=upload" \
|
||||
-F "etude_id=E-001" \
|
||||
-F "utilisateur_id=U-123" \
|
||||
http://localhost:8000/api/import
|
||||
|
||||
status: ## Vérifier le statut de tous les services
|
||||
@echo "=== Statut des services ==="
|
||||
@make ps-simple
|
||||
@echo ""
|
||||
@echo "=== Test de connectivité ==="
|
||||
@curl -s http://localhost:8000/api/health || echo "API non accessible"
|
@ -1,88 +0,0 @@
|
||||
version: "3.9"
|
||||
|
||||
# Configuration de développement avec volumes montés et debugging
|
||||
services:
|
||||
host-api:
|
||||
build:
|
||||
context: ./docker/host-api
|
||||
volumes:
|
||||
- ./services/host_api:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
environment:
|
||||
- DEBUG=true
|
||||
- LOG_LEVEL=debug
|
||||
ports:
|
||||
- "8000:8000"
|
||||
command: ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- minio
|
||||
|
||||
worker:
|
||||
build:
|
||||
context: ./docker/worker
|
||||
volumes:
|
||||
- ./services/worker:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
environment:
|
||||
- DEBUG=true
|
||||
- LOG_LEVEL=debug
|
||||
command: ["celery", "-A", "worker", "worker", "--loglevel=debug"]
|
||||
depends_on:
|
||||
- host-api
|
||||
|
||||
postgres:
|
||||
image: postgres:16
|
||||
environment:
|
||||
POSTGRES_USER: notariat
|
||||
POSTGRES_PASSWORD: notariat_pwd
|
||||
POSTGRES_DB: notariat
|
||||
volumes:
|
||||
- pgdata_dev:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis_dev:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-01-13T00-00-00Z
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: minio
|
||||
MINIO_ROOT_PASSWORD: minio_pwd
|
||||
volumes:
|
||||
- minio_dev:/data
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
volumes:
|
||||
- ollama_dev:/root/.ollama
|
||||
ports:
|
||||
- "11434:11434"
|
||||
environment:
|
||||
- OLLAMA_HOST=0.0.0.0
|
||||
|
||||
anythingsqlite:
|
||||
image: kevincharm/anythingllm:latest
|
||||
environment:
|
||||
- DISABLE_AUTH=true
|
||||
ports:
|
||||
- "3001:3001"
|
||||
depends_on:
|
||||
- ollama
|
||||
|
||||
volumes:
|
||||
pgdata_dev:
|
||||
redis_dev:
|
||||
minio_dev:
|
||||
ollama_dev:
|
@ -1,58 +0,0 @@
|
||||
version: "3.9"
|
||||
|
||||
# Configuration pour les tests d'intégration
|
||||
services:
|
||||
postgres-test:
|
||||
image: postgres:16
|
||||
environment:
|
||||
POSTGRES_USER: test_notariat
|
||||
POSTGRES_PASSWORD: test_pwd
|
||||
POSTGRES_DB: test_notariat
|
||||
volumes:
|
||||
- pgdata_test:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5433:5432"
|
||||
|
||||
redis-test:
|
||||
image: redis:7
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis_test:/data
|
||||
ports:
|
||||
- "6380:6379"
|
||||
|
||||
minio-test:
|
||||
image: minio/minio:RELEASE.2025-01-13T00-00-00Z
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: test_minio
|
||||
MINIO_ROOT_PASSWORD: test_minio_pwd
|
||||
volumes:
|
||||
- minio_test:/data
|
||||
ports:
|
||||
- "9002:9000"
|
||||
- "9003:9001"
|
||||
|
||||
ollama-test:
|
||||
image: ollama/ollama:latest
|
||||
volumes:
|
||||
- ollama_test:/root/.ollama
|
||||
ports:
|
||||
- "11435:11434"
|
||||
environment:
|
||||
- OLLAMA_HOST=0.0.0.0
|
||||
|
||||
anythingsqlite-test:
|
||||
image: kevincharm/anythingllm:latest
|
||||
environment:
|
||||
- DISABLE_AUTH=true
|
||||
ports:
|
||||
- "3002:3001"
|
||||
depends_on:
|
||||
- ollama-test
|
||||
|
||||
volumes:
|
||||
pgdata_test:
|
||||
redis_test:
|
||||
minio_test:
|
||||
ollama_test:
|
452
docker-compose.yml
Normal file
452
docker-compose.yml
Normal file
@ -0,0 +1,452 @@
|
||||
x-env: &default-env
|
||||
TZ: ${TZ}
|
||||
PUID: "1000"
|
||||
PGID: "1000"
|
||||
|
||||
# Configuration DNS et réseau pour 4NK_IA_back
|
||||
x-4nk-ia-extra-hosts: &x-4nk-ia-extra-hosts
|
||||
extra_hosts:
|
||||
- "4nk-ia-api.local:172.23.0.10"
|
||||
- "4nk-ia-worker.local:172.23.0.11"
|
||||
- "4nk-ia-postgres.local:172.23.0.12"
|
||||
- "4nk-ia-redis.local:172.23.0.13"
|
||||
- "4nk-ia-minio.local:172.23.0.14"
|
||||
- "4nk-ia-ollama.local:172.23.0.15"
|
||||
- "4nk-ia-anythingllm.local:172.23.0.16"
|
||||
- "4nk-ia-neo4j.local:172.23.0.17"
|
||||
- "4nk-ia-opensearch.local:172.23.0.18"
|
||||
|
||||
services:
|
||||
|
||||
# ==================== SERVICES DE BASE ====================
|
||||
|
||||
postgres:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: postgres:16
|
||||
container_name: 4nk-ia-postgres.local
|
||||
hostname: 4nk-ia-postgres.local
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1 # Gateway Docker pour accéder à dnsmasq
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.12
|
||||
|
||||
postgres-test:
|
||||
image: postgres:16
|
||||
container_name: 4nk-ia-postgres-test.local
|
||||
hostname: 4nk-ia-postgres-test.local
|
||||
environment:
|
||||
POSTGRES_USER: test_notariat
|
||||
POSTGRES_PASSWORD: test_pwd
|
||||
POSTGRES_DB: test_notariat
|
||||
volumes:
|
||||
- pgdata_test:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5433:5432"
|
||||
restart: unless-stopped
|
||||
profiles: ["test"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.22
|
||||
|
||||
redis:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: redis:7
|
||||
container_name: 4nk-ia-redis.local
|
||||
hostname: 4nk-ia-redis.local
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.13
|
||||
|
||||
redis-test:
|
||||
image: redis:7
|
||||
container_name: 4nk-ia-redis-test.local
|
||||
hostname: 4nk-ia-redis-test.local
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis_test:/data
|
||||
ports:
|
||||
- "6380:6379"
|
||||
restart: unless-stopped
|
||||
profiles: ["test"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.23
|
||||
|
||||
minio:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: minio/minio:latest
|
||||
container_name: 4nk-ia-minio.local
|
||||
hostname: 4nk-ia-minio.local
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- minio:/data
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.14
|
||||
|
||||
minio-test:
|
||||
image: minio/minio:latest
|
||||
container_name: 4nk-ia-minio-test.local
|
||||
hostname: 4nk-ia-minio-test.local
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: test_minio
|
||||
MINIO_ROOT_PASSWORD: test_minio_pwd
|
||||
volumes:
|
||||
- minio_test:/data
|
||||
ports:
|
||||
- "9002:9000"
|
||||
- "9003:9001"
|
||||
restart: unless-stopped
|
||||
profiles: ["test"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.24
|
||||
|
||||
# ==================== SERVICES IA ET RAG ====================
|
||||
|
||||
ollama:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: ollama/ollama:latest
|
||||
container_name: 4nk-ia-ollama.local
|
||||
hostname: 4nk-ia-ollama.local
|
||||
volumes:
|
||||
- ollama:/root/.ollama
|
||||
ports:
|
||||
- "11435:11434" # Port modifié pour éviter les conflits
|
||||
environment:
|
||||
- OLLAMA_HOST=0.0.0.0
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.15
|
||||
|
||||
ollama-test:
|
||||
image: ollama/ollama:latest
|
||||
container_name: 4nk-ia-ollama-test.local
|
||||
hostname: 4nk-ia-ollama-test.local
|
||||
volumes:
|
||||
- ollama_test:/root/.ollama
|
||||
ports:
|
||||
- "11436:11434"
|
||||
environment:
|
||||
- OLLAMA_HOST=0.0.0.0
|
||||
restart: unless-stopped
|
||||
profiles: ["test"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.25
|
||||
|
||||
anythingsqlite:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: mintplexlabs/anythingllm:latest
|
||||
container_name: 4nk-ia-anythingllm.local
|
||||
hostname: 4nk-ia-anythingllm.local
|
||||
environment:
|
||||
- DISABLE_AUTH=true
|
||||
- STORAGE_DIR=/app/server/storage
|
||||
depends_on:
|
||||
- ollama
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- anythingllm:/app/server/storage
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.16
|
||||
|
||||
anythingsqlite-test:
|
||||
image: mintplexlabs/anythingllm:latest
|
||||
container_name: 4nk-ia-anythingllm-test.local
|
||||
hostname: 4nk-ia-anythingllm-test.local
|
||||
environment:
|
||||
- DISABLE_AUTH=true
|
||||
- STORAGE_DIR=/app/server/storage
|
||||
depends_on:
|
||||
- ollama-test
|
||||
ports:
|
||||
- "3002:3001"
|
||||
volumes:
|
||||
- anythingllm_test:/app/server/storage
|
||||
restart: unless-stopped
|
||||
profiles: ["test"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.26
|
||||
|
||||
# ==================== SERVICES DE DONNÉES ====================
|
||||
|
||||
neo4j:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: neo4j:5
|
||||
container_name: 4nk-ia-neo4j.local
|
||||
hostname: 4nk-ia-neo4j.local
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_AUTH}
|
||||
volumes:
|
||||
- neo4j:/data
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.17
|
||||
|
||||
opensearch:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
image: opensearchproject/opensearch:2.14.0
|
||||
container_name: 4nk-ia-opensearch.local
|
||||
hostname: 4nk-ia-opensearch.local
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=OpenSearch2025!
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- opensearch:/usr/share/opensearch/data
|
||||
ports:
|
||||
- "9200:9200"
|
||||
restart: unless-stopped
|
||||
profiles: ["production", "development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.18
|
||||
|
||||
# ==================== SERVICES APPLICATIFS ====================
|
||||
|
||||
host-api:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
build:
|
||||
context: ./docker/host-api
|
||||
dockerfile: Dockerfile
|
||||
container_name: 4nk-ia-api.local
|
||||
hostname: 4nk-ia-api.local
|
||||
labels:
|
||||
- logging=promtail
|
||||
- project=4nk_ia_back
|
||||
env_file: ./.env
|
||||
environment:
|
||||
<<: *default-env
|
||||
DATABASE_URL: postgresql+psycopg://$POSTGRES_USER:$POSTGRES_PASSWORD@4nk-ia-postgres.local:5432/$POSTGRES_DB
|
||||
REDIS_URL: redis://4nk-ia-redis.local:6379/0
|
||||
MINIO_ENDPOINT: 4nk-ia-minio.local:9000
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
ANYLLM_BASE_URL: http://4nk-ia-anythingllm.local:3001
|
||||
ANYLLM_API_KEY: ${ANYLLM_API_KEY}
|
||||
OLLAMA_BASE_URL: http://4nk-ia-ollama.local:11434
|
||||
OPENSEARCH_URL: http://4nk-ia-opensearch.local:9200
|
||||
NEO4J_URL: bolt://4nk-ia-neo4j.local:7687
|
||||
NEO4J_AUTH: ${NEO4J_AUTH}
|
||||
# Configuration de l'API
|
||||
API_HOST: 0.0.0.0
|
||||
API_PORT: 8000
|
||||
API_WORKERS: 4
|
||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||
LOG_FORMAT: ${LOG_FORMAT:-json}
|
||||
# Sécurité
|
||||
SECRET_KEY: ${SECRET_KEY:-your_secret_key_here}
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-30}
|
||||
volumes:
|
||||
- ./services/host_api:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
- ./ops/seed/schemas:/schemas:ro
|
||||
- api_logs:/app/logs
|
||||
ports:
|
||||
- "8001:8000" # Port externe 8001 pour éviter les conflits
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
minio:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
profiles: ["production"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.10
|
||||
|
||||
host-api-dev:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
build:
|
||||
context: ./docker/host-api
|
||||
dockerfile: Dockerfile
|
||||
container_name: 4nk-ia-api-dev.local
|
||||
hostname: 4nk-ia-api-dev.local
|
||||
volumes:
|
||||
- ./services/host_api:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
environment:
|
||||
- DEBUG=true
|
||||
- LOG_LEVEL=debug
|
||||
- DATABASE_URL=postgresql+psycopg://notariat:notariat_pwd@4nk-ia-postgres.local:5432/notariat
|
||||
- REDIS_URL=redis://4nk-ia-redis.local:6379/0
|
||||
ports:
|
||||
- "8000:8000" # Port de développement
|
||||
command: ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]
|
||||
depends_on:
|
||||
- postgres
|
||||
- redis
|
||||
- minio
|
||||
restart: unless-stopped
|
||||
profiles: ["development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.30
|
||||
|
||||
worker:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
build:
|
||||
context: ./
|
||||
dockerfile: docker/worker/Dockerfile
|
||||
container_name: 4nk-ia-worker.local
|
||||
hostname: 4nk-ia-worker.local
|
||||
labels:
|
||||
- logging=promtail
|
||||
- project=4nk_ia_back
|
||||
env_file: ./.env
|
||||
environment:
|
||||
<<: *default-env
|
||||
DATABASE_URL: postgresql+psycopg://$POSTGRES_USER:$POSTGRES_PASSWORD@4nk-ia-postgres.local:5432/$POSTGRES_DB
|
||||
REDIS_URL: redis://4nk-ia-redis.local:6379/0
|
||||
MINIO_ENDPOINT: 4nk-ia-minio.local:9000
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
ANYLLM_BASE_URL: http://4nk-ia-anythingllm.local:3001
|
||||
ANYLLM_API_KEY: ${ANYLLM_API_KEY}
|
||||
OLLAMA_BASE_URL: http://4nk-ia-ollama.local:11434
|
||||
OPENSEARCH_URL: http://4nk-ia-opensearch.local:9200
|
||||
NEO4J_URL: bolt://4nk-ia-neo4j.local:7687
|
||||
NEO4J_AUTH: ${NEO4J_AUTH}
|
||||
volumes:
|
||||
- ./services/worker:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
depends_on:
|
||||
- host-api
|
||||
restart: unless-stopped
|
||||
profiles: ["production"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.11
|
||||
|
||||
worker-dev:
|
||||
<<: *x-4nk-ia-extra-hosts
|
||||
build:
|
||||
context: ./docker/worker
|
||||
container_name: 4nk-ia-worker-dev.local
|
||||
hostname: 4nk-ia-worker-dev.local
|
||||
volumes:
|
||||
- ./services/worker:/app
|
||||
- ./ops/seed:/seed:ro
|
||||
environment:
|
||||
- DEBUG=true
|
||||
- LOG_LEVEL=debug
|
||||
- DATABASE_URL=postgresql+psycopg://notariat:notariat_pwd@4nk-ia-postgres.local:5432/notariat
|
||||
- REDIS_URL=redis://4nk-ia-redis.local:6379/0
|
||||
command: ["celery", "-A", "worker", "worker", "--loglevel=debug"]
|
||||
depends_on:
|
||||
- host-api-dev
|
||||
restart: unless-stopped
|
||||
profiles: ["development"]
|
||||
dns:
|
||||
- 172.23.0.1
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
ipv4_address: 172.23.0.31
|
||||
|
||||
volumes:
|
||||
# Volumes de production/développement
|
||||
pgdata:
|
||||
redis:
|
||||
minio:
|
||||
ollama:
|
||||
neo4j:
|
||||
opensearch:
|
||||
anythingllm:
|
||||
api_logs:
|
||||
|
||||
# Volumes de test
|
||||
pgdata_test:
|
||||
redis_test:
|
||||
minio_test:
|
||||
ollama_test:
|
||||
anythingllm_test:
|
||||
|
||||
networks:
|
||||
4nk_ia_network:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.23.0.0/16
|
||||
gateway: 172.23.0.1
|
@ -11,4 +11,4 @@ RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY services/worker /app
|
||||
|
||||
CMD ["python", "worker.py"]
|
||||
CMD ["celery", "-A", "worker", "worker", "--loglevel=info"]
|
||||
|
@ -209,9 +209,7 @@ curl "http://localhost:8000/api/notary/document/{document_id}/analysis"
|
||||
cd services/host_api
|
||||
uvicorn app:app --host 0.0.0.0 --port 8000
|
||||
|
||||
# Démarrer l'interface web (dans un autre terminal)
|
||||
cd services/web_interface
|
||||
python start_web.py
|
||||
# L'interface web est gérée par le projet 4NK_IA_front séparé
|
||||
```
|
||||
|
||||
#### Accès
|
||||
|
@ -440,9 +440,7 @@ cd services/worker
|
||||
source ../../venv/bin/activate
|
||||
celery -A worker worker --loglevel=info &
|
||||
|
||||
# Démarrage de l'interface web
|
||||
cd services/web_interface
|
||||
python3 start_web.py 8081 &
|
||||
# L'interface web est gérée par le projet 4NK_IA_front séparé
|
||||
```
|
||||
|
||||
### **3. Vérification du Démarrage**
|
||||
|
9
hosts.4nk-ia
Normal file
9
hosts.4nk-ia
Normal file
@ -0,0 +1,9 @@
|
||||
172.23.0.10 4nk-ia-api.local
|
||||
172.23.0.11 4nk-ia-worker.local
|
||||
172.23.0.12 4nk-ia-postgres.local
|
||||
172.23.0.13 4nk-ia-redis.local
|
||||
172.23.0.14 4nk-ia-minio.local
|
||||
172.23.0.15 4nk-ia-ollama.local
|
||||
172.23.0.16 4nk-ia-anythingllm.local
|
||||
172.23.0.17 4nk-ia-neo4j.local
|
||||
172.23.0.18 4nk-ia-opensearch.local
|
24
hosts.merge
Normal file
24
hosts.merge
Normal file
@ -0,0 +1,24 @@
|
||||
172.23.0.10 4nk-ia-api.local
|
||||
172.23.0.11 4nk-ia-worker.local
|
||||
172.23.0.12 4nk-ia-postgres.local
|
||||
172.23.0.13 4nk-ia-redis.local
|
||||
172.23.0.14 4nk-ia-minio.local
|
||||
172.23.0.15 4nk-ia-ollama.local
|
||||
172.23.0.16 4nk-ia-anythingllm.local
|
||||
172.23.0.17 4nk-ia-neo4j.local
|
||||
172.23.0.18 4nk-ia-opensearch.local
|
||||
172.20.0.10 tor.local
|
||||
172.20.0.11 bitcoin.local
|
||||
172.20.0.12 blindbit-oracle.local
|
||||
172.20.0.13 sdk-storage.local
|
||||
172.20.0.14 sdk-relay1.local
|
||||
172.20.0.15 sdk-relay2.local
|
||||
172.20.0.16 sdk-relay3.local
|
||||
172.20.0.17 sdk-signer.local
|
||||
172.20.0.18 ihm-client.local
|
||||
172.20.0.32 coffre-front.local
|
||||
172.20.0.33 coffre-back-mini.local
|
||||
172.20.0.50 grafana-central.local
|
||||
172.20.0.51 loki.local
|
||||
172.20.0.52 prometheus.local
|
||||
172.20.0.53 promtail.local
|
15
hosts.sdk
Normal file
15
hosts.sdk
Normal file
@ -0,0 +1,15 @@
|
||||
172.20.0.10 tor.local
|
||||
172.20.0.11 bitcoin.local
|
||||
172.20.0.12 blindbit-oracle.local
|
||||
172.20.0.13 sdk-storage.local
|
||||
172.20.0.14 sdk-relay1.local
|
||||
172.20.0.15 sdk-relay2.local
|
||||
172.20.0.16 sdk-relay3.local
|
||||
172.20.0.17 sdk-signer.local
|
||||
172.20.0.18 ihm-client.local
|
||||
172.20.0.32 coffre-front.local
|
||||
172.20.0.33 coffre-back-mini.local
|
||||
172.20.0.50 grafana-central.local
|
||||
172.20.0.51 loki.local
|
||||
172.20.0.52 prometheus.local
|
||||
172.20.0.53 promtail.local
|
@ -1,71 +0,0 @@
|
||||
# Configuration du projet
|
||||
PROJECT_NAME=notariat
|
||||
DOMAIN=localhost
|
||||
TZ=Europe/Paris
|
||||
|
||||
# Base de données PostgreSQL
|
||||
POSTGRES_USER=notariat
|
||||
POSTGRES_PASSWORD=notariat_pwd
|
||||
POSTGRES_DB=notariat
|
||||
|
||||
# Redis
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# MinIO (Stockage S3-compatible)
|
||||
MINIO_ROOT_USER=minio
|
||||
MINIO_ROOT_PASSWORD=minio_pwd
|
||||
MINIO_BUCKET=ingest
|
||||
|
||||
# AnythingLLM
|
||||
ANYLLM_API_KEY=change_me
|
||||
ANYLLM_BASE_URL=http://anythingllm:3001
|
||||
ANYLLM_WORKSPACE_NORMES=workspace_normes
|
||||
ANYLLM_WORKSPACE_TRAMES=workspace_trames
|
||||
ANYLLM_WORKSPACE_ACTES=workspace_actes
|
||||
|
||||
# Ollama (LLM local)
|
||||
OLLAMA_BASE_URL=http://ollama:11434
|
||||
OLLAMA_MODELS=llama3:8b,mistral:7b
|
||||
|
||||
# Neo4j (Graphe de connaissances)
|
||||
NEO4J_AUTH=neo4j/neo4j_pwd
|
||||
|
||||
# OpenSearch (Recherche plein-texte)
|
||||
OPENSEARCH_PASSWORD=opensearch_pwd
|
||||
|
||||
# Traefik (Passerelle HTTP)
|
||||
TRAEFIK_ACME_EMAIL=ops@example.org
|
||||
|
||||
# Configuration de l'API
|
||||
API_HOST=0.0.0.0
|
||||
API_PORT=8000
|
||||
API_WORKERS=1
|
||||
|
||||
# Configuration des workers
|
||||
WORKER_CONCURRENCY=2
|
||||
WORKER_LOGLEVEL=info
|
||||
|
||||
# Seuils de qualité
|
||||
OCR_CONFIDENCE_THRESHOLD=0.75
|
||||
CLASSIFICATION_CONFIDENCE_THRESHOLD=0.75
|
||||
MANUAL_REVIEW_CER_THRESHOLD=0.08
|
||||
|
||||
# URLs des APIs externes
|
||||
CADASTRE_API_URL=https://apicarto.ign.fr/api/cadastre
|
||||
GEORISQUES_API_URL=https://www.georisques.gouv.fr/api
|
||||
BODACC_API_URL=https://bodacc-datadila.opendatasoft.com/api
|
||||
INFOGREFFE_API_URL=https://entreprise.api.gouv.fr/v2/infogreffe
|
||||
RBE_API_URL=https://www.data.gouv.fr/api/1/datasets/registre-des-beneficiaires-effectifs
|
||||
|
||||
# Configuration de sécurité
|
||||
JWT_SECRET_KEY=your-secret-key-change-in-production
|
||||
ENCRYPTION_KEY=your-encryption-key-change-in-production
|
||||
|
||||
# Configuration de monitoring
|
||||
PROMETHEUS_ENABLED=true
|
||||
GRAFANA_ENABLED=true
|
||||
SENTRY_DSN=
|
||||
|
||||
# Configuration de logs
|
||||
LOG_LEVEL=INFO
|
||||
LOG_FORMAT=json
|
@ -1,21 +0,0 @@
|
||||
# Configuration simplifiée sans IA
|
||||
PROJECT_NAME=notariat
|
||||
DOMAIN=localhost
|
||||
TZ=Europe/Paris
|
||||
|
||||
# Base de données PostgreSQL
|
||||
POSTGRES_USER=notariat
|
||||
POSTGRES_PASSWORD=notariat_pwd
|
||||
POSTGRES_DB=notariat
|
||||
|
||||
# Redis
|
||||
REDIS_PASSWORD=
|
||||
|
||||
# MinIO (stockage objet)
|
||||
MINIO_ROOT_USER=minio
|
||||
MINIO_ROOT_PASSWORD=minio_pwd
|
||||
MINIO_BUCKET=ingest
|
||||
|
||||
# Configuration de développement
|
||||
DEBUG=true
|
||||
LOG_LEVEL=debug
|
17
infra/dnsmasq-4nk-ia.conf
Normal file
17
infra/dnsmasq-4nk-ia.conf
Normal file
@ -0,0 +1,17 @@
|
||||
# dnsmasq config for 4NK_IA_back - listens on all interfaces:53
|
||||
no-dhcp-interface=
|
||||
port=53
|
||||
interface=*
|
||||
bind-interfaces
|
||||
log-queries
|
||||
|
||||
# 4NK_IA_back Docker hosts
|
||||
address=/4nk-ia-api.local/172.23.0.10
|
||||
address=/4nk-ia-worker.local/172.23.0.11
|
||||
address=/4nk-ia-postgres.local/172.23.0.12
|
||||
address=/4nk-ia-redis.local/172.23.0.13
|
||||
address=/4nk-ia-minio.local/172.23.0.14
|
||||
address=/4nk-ia-ollama.local/172.23.0.15
|
||||
address=/4nk-ia-anythingllm.local/172.23.0.16
|
||||
address=/4nk-ia-neo4j.local/172.23.0.17
|
||||
address=/4nk-ia-opensearch.local/172.23.0.18
|
@ -1,182 +0,0 @@
|
||||
x-env: &default-env
|
||||
TZ: ${TZ}
|
||||
PUID: "1000"
|
||||
PGID: "1000"
|
||||
|
||||
services:
|
||||
|
||||
postgres:
|
||||
image: postgres:16
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
ports:
|
||||
- "5432:5432"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
restart: unless-stopped
|
||||
|
||||
redis:
|
||||
image: redis:7
|
||||
command: ["redis-server", "--appendonly", "yes"]
|
||||
volumes:
|
||||
- redis:/data
|
||||
ports:
|
||||
- "6379:6379"
|
||||
restart: unless-stopped
|
||||
|
||||
minio:
|
||||
image: minio/minio:latest
|
||||
command: server /data --console-address ":9001"
|
||||
environment:
|
||||
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
|
||||
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
|
||||
volumes:
|
||||
- minio:/data
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9001:9001"
|
||||
restart: unless-stopped
|
||||
|
||||
anythingsqlite:
|
||||
image: mintplexlabs/anythingllm:latest
|
||||
environment:
|
||||
- DISABLE_AUTH=true
|
||||
depends_on:
|
||||
- ollama
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- anythingllm:/app/server/storage
|
||||
container_name: anythingllm
|
||||
restart: unless-stopped
|
||||
|
||||
ollama:
|
||||
image: ollama/ollama:latest
|
||||
volumes:
|
||||
- ollama:/root/.ollama
|
||||
ports:
|
||||
- "11434:11434"
|
||||
restart: unless-stopped
|
||||
|
||||
neo4j:
|
||||
image: neo4j:5
|
||||
environment:
|
||||
- NEO4J_AUTH=${NEO4J_AUTH}
|
||||
volumes:
|
||||
- neo4j:/data
|
||||
ports:
|
||||
- "7474:7474"
|
||||
- "7687:7687"
|
||||
restart: unless-stopped
|
||||
|
||||
opensearch:
|
||||
image: opensearchproject/opensearch:2.14.0
|
||||
environment:
|
||||
- discovery.type=single-node
|
||||
- OPENSEARCH_INITIAL_ADMIN_PASSWORD=${OPENSEARCH_PASSWORD}
|
||||
ulimits:
|
||||
memlock:
|
||||
soft: -1
|
||||
hard: -1
|
||||
volumes:
|
||||
- opensearch:/usr/share/opensearch/data
|
||||
ports:
|
||||
- "9200:9200"
|
||||
restart: unless-stopped
|
||||
|
||||
host-api:
|
||||
build:
|
||||
context: ../docker/host-api
|
||||
dockerfile: Dockerfile
|
||||
labels:
|
||||
- logging=promtail
|
||||
- project=4nk_ia_back
|
||||
env_file: ./.env
|
||||
environment:
|
||||
<<: *default-env
|
||||
DATABASE_URL: postgresql+psycopg://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_DB
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
MINIO_ENDPOINT: minio:9000
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
ANYLLM_BASE_URL: ${ANYLLM_BASE_URL}
|
||||
ANYLLM_API_KEY: ${ANYLLM_API_KEY}
|
||||
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL}
|
||||
OPENSEARCH_URL: http://opensearch:9200
|
||||
NEO4J_URL: bolt://neo4j:7687
|
||||
NEO4J_AUTH: ${NEO4J_AUTH}
|
||||
# Configuration de l'API
|
||||
API_HOST: 0.0.0.0
|
||||
API_PORT: 8000
|
||||
API_WORKERS: 4
|
||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||
LOG_FORMAT: ${LOG_FORMAT:-json}
|
||||
# Sécurité
|
||||
SECRET_KEY: ${SECRET_KEY:-your_secret_key_here}
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-30}
|
||||
volumes:
|
||||
- ../services/host_api:/app
|
||||
- ../ops/seed:/seed:ro
|
||||
- ../ops/seed/schemas:/schemas:ro
|
||||
- api_logs:/app/logs
|
||||
ports:
|
||||
- "8000:8000"
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_started
|
||||
minio:
|
||||
condition: service_started
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:8000/api/health"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
worker:
|
||||
build:
|
||||
context: ../
|
||||
dockerfile: docker/worker/Dockerfile
|
||||
labels:
|
||||
- logging=promtail
|
||||
- project=4nk_ia_back
|
||||
env_file: ./.env
|
||||
environment:
|
||||
<<: *default-env
|
||||
DATABASE_URL: postgresql+psycopg://$POSTGRES_USER:$POSTGRES_PASSWORD@postgres:5432/$POSTGRES_DB
|
||||
REDIS_URL: redis://redis:6379/0
|
||||
MINIO_ENDPOINT: minio:9000
|
||||
MINIO_BUCKET: ${MINIO_BUCKET}
|
||||
ANYLLM_BASE_URL: ${ANYLLM_BASE_URL}
|
||||
ANYLLM_API_KEY: ${ANYLLM_API_KEY}
|
||||
OLLAMA_BASE_URL: ${OLLAMA_BASE_URL}
|
||||
OPENSEARCH_URL: http://opensearch:9200
|
||||
NEO4J_URL: bolt://neo4j:7687
|
||||
NEO4J_AUTH: ${NEO4J_AUTH}
|
||||
volumes:
|
||||
- ../services/worker:/app
|
||||
- ../ops/seed:/seed:ro
|
||||
depends_on:
|
||||
- host-api
|
||||
restart: unless-stopped
|
||||
|
||||
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
redis:
|
||||
minio:
|
||||
ollama:
|
||||
neo4j:
|
||||
opensearch:
|
||||
anythingllm:
|
||||
api_logs:
|
43
infra/setup-dnsmasq.sh
Executable file
43
infra/setup-dnsmasq.sh
Executable file
@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de configuration dnsmasq pour 4NK_IA_back
|
||||
set -euo pipefail
|
||||
|
||||
echo "🔧 Configuration de dnsmasq pour 4NK_IA_back"
|
||||
|
||||
# Vérifier si dnsmasq est installé
|
||||
if ! command -v dnsmasq &> /dev/null; then
|
||||
echo "📦 Installation de dnsmasq..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y dnsmasq
|
||||
fi
|
||||
|
||||
# Créer le répertoire de configuration
|
||||
sudo mkdir -p /etc/dnsmasq.d
|
||||
|
||||
# Copier la configuration 4NK_IA_back
|
||||
echo "📝 Copie de la configuration dnsmasq..."
|
||||
sudo cp dnsmasq-4nk-ia.conf /etc/dnsmasq.d/4nk-ia.conf
|
||||
|
||||
# Redémarrer dnsmasq
|
||||
echo "🔄 Redémarrage de dnsmasq..."
|
||||
sudo systemctl restart dnsmasq
|
||||
sudo systemctl enable dnsmasq
|
||||
|
||||
# Vérifier le statut
|
||||
echo "✅ Vérification du statut de dnsmasq..."
|
||||
sudo systemctl status dnsmasq --no-pager -l
|
||||
|
||||
echo "🎉 Configuration dnsmasq terminée !"
|
||||
echo ""
|
||||
echo "📋 Services disponibles :"
|
||||
echo " - 4nk-ia-api.local:172.21.0.10"
|
||||
echo " - 4nk-ia-worker.local:172.21.0.11"
|
||||
echo " - 4nk-ia-postgres.local:172.21.0.12"
|
||||
echo " - 4nk-ia-redis.local:172.21.0.13"
|
||||
echo " - 4nk-ia-minio.local:172.21.0.14"
|
||||
echo " - 4nk-ia-ollama.local:172.21.0.15"
|
||||
echo " - 4nk-ia-anythingllm.local:172.21.0.16"
|
||||
echo " - 4nk-ia-neo4j.local:172.21.0.17"
|
||||
echo " - 4nk-ia-opensearch.local:172.21.0.18"
|
||||
|
218
manage.sh
Executable file
218
manage.sh
Executable file
@ -0,0 +1,218 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de gestion principal pour 4NK_IA_back
|
||||
set -euo pipefail
|
||||
|
||||
# Couleurs pour les messages
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Fonction d'affichage des messages
|
||||
log_info() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
log_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Fonction d'aide
|
||||
show_help() {
|
||||
cat << EOF
|
||||
🔧 Gestionnaire 4NK_IA_back
|
||||
|
||||
Usage: $0 <command> [options]
|
||||
|
||||
COMMANDES PRINCIPALES:
|
||||
up [profile] Démarrer les services (production|development|test)
|
||||
down Arrêter tous les services
|
||||
restart [profile] Redémarrer les services
|
||||
status Afficher le statut des services
|
||||
logs [service] Afficher les logs des services
|
||||
shell [service] Ouvrir un shell dans un conteneur
|
||||
clean Nettoyer les conteneurs et volumes
|
||||
setup-dns Configurer dnsmasq pour les noms .local
|
||||
|
||||
PROFILS DISPONIBLES:
|
||||
production Services de production (défaut)
|
||||
development Services de développement avec volumes montés
|
||||
test Services de test isolés
|
||||
|
||||
EXEMPLES:
|
||||
$0 up # Démarrer en production
|
||||
$0 up development # Démarrer en développement
|
||||
$0 logs api # Voir les logs de l'API
|
||||
$0 shell postgres # Ouvrir un shell PostgreSQL
|
||||
$0 clean # Nettoyer tout
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
# Fonction pour démarrer les services
|
||||
start_services() {
|
||||
local profile=${1:-production}
|
||||
|
||||
log_info "Démarrage des services avec le profil: $profile"
|
||||
|
||||
case $profile in
|
||||
production|development|test)
|
||||
docker-compose --profile "$profile" up -d
|
||||
;;
|
||||
*)
|
||||
log_error "Profil invalide: $profile. Utilisez: production, development, ou test"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
log_success "Services démarrés avec le profil: $profile"
|
||||
log_info "Vérification du statut..."
|
||||
docker-compose ps
|
||||
}
|
||||
|
||||
# Fonction pour arrêter les services
|
||||
stop_services() {
|
||||
log_info "Arrêt des services..."
|
||||
docker-compose down
|
||||
log_success "Services arrêtés"
|
||||
}
|
||||
|
||||
# Fonction pour redémarrer les services
|
||||
restart_services() {
|
||||
local profile=${1:-production}
|
||||
log_info "Redémarrage des services avec le profil: $profile"
|
||||
stop_services
|
||||
start_services "$profile"
|
||||
}
|
||||
|
||||
# Fonction pour afficher le statut
|
||||
show_status() {
|
||||
log_info "Statut des services:"
|
||||
docker-compose ps
|
||||
|
||||
echo ""
|
||||
log_info "Réseaux Docker:"
|
||||
docker network ls | grep 4nk_ia
|
||||
|
||||
echo ""
|
||||
log_info "Volumes Docker:"
|
||||
docker volume ls | grep 4nk_ia
|
||||
}
|
||||
|
||||
# Fonction pour afficher les logs
|
||||
show_logs() {
|
||||
local service=${1:-}
|
||||
|
||||
if [[ -n "$service" ]]; then
|
||||
log_info "Logs du service: $service"
|
||||
docker-compose logs -f "$service"
|
||||
else
|
||||
log_info "Logs de tous les services:"
|
||||
docker-compose logs -f
|
||||
fi
|
||||
}
|
||||
|
||||
# Fonction pour ouvrir un shell
|
||||
open_shell() {
|
||||
local service=${1:-host-api}
|
||||
|
||||
log_info "Ouverture d'un shell dans le service: $service"
|
||||
docker-compose exec "$service" /bin/bash
|
||||
}
|
||||
|
||||
# Fonction de nettoyage
|
||||
clean_all() {
|
||||
log_warning "Cette action va supprimer tous les conteneurs, réseaux et volumes 4NK_IA_back"
|
||||
read -p "Êtes-vous sûr ? (y/N): " -n 1 -r
|
||||
echo
|
||||
|
||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
||||
log_info "Nettoyage en cours..."
|
||||
docker-compose down -v --remove-orphans
|
||||
docker system prune -f
|
||||
log_success "Nettoyage terminé"
|
||||
else
|
||||
log_info "Nettoyage annulé"
|
||||
fi
|
||||
}
|
||||
|
||||
# Fonction pour configurer dnsmasq
|
||||
setup_dns() {
|
||||
log_info "Configuration de dnsmasq pour les noms .local"
|
||||
|
||||
if [[ -f "./infra/setup-dnsmasq.sh" ]]; then
|
||||
sudo ./infra/setup-dnsmasq.sh
|
||||
else
|
||||
log_error "Script setup-dnsmasq.sh non trouvé"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Fonction pour tester l'API
|
||||
test_api() {
|
||||
log_info "Test de l'API..."
|
||||
|
||||
# Attendre que l'API soit prête
|
||||
log_info "Attente du démarrage de l'API..."
|
||||
sleep 10
|
||||
|
||||
# Test de santé
|
||||
if curl -s http://localhost:8001/api/health > /dev/null; then
|
||||
log_success "API accessible sur http://localhost:8001"
|
||||
curl -s http://localhost:8001/api/health | jq .
|
||||
else
|
||||
log_error "API non accessible"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Gestion des arguments
|
||||
case "${1:-help}" in
|
||||
up)
|
||||
start_services "${2:-production}"
|
||||
;;
|
||||
down)
|
||||
stop_services
|
||||
;;
|
||||
restart)
|
||||
restart_services "${2:-production}"
|
||||
;;
|
||||
status)
|
||||
show_status
|
||||
;;
|
||||
logs)
|
||||
show_logs "${2:-}"
|
||||
;;
|
||||
shell)
|
||||
open_shell "${2:-host-api}"
|
||||
;;
|
||||
clean)
|
||||
clean_all
|
||||
;;
|
||||
setup-dns)
|
||||
setup_dns
|
||||
;;
|
||||
test)
|
||||
test_api
|
||||
;;
|
||||
help|--help|-h)
|
||||
show_help
|
||||
;;
|
||||
*)
|
||||
log_error "Commande inconnue: $1"
|
||||
echo ""
|
||||
show_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
File diff suppressed because it is too large
Load Diff
370
services/web_interface/bootstrap.min.css
vendored
370
services/web_interface/bootstrap.min.css
vendored
@ -1,370 +0,0 @@
|
||||
/* Bootstrap CSS minimal pour 4NK Notariat */
|
||||
:root {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 100%;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
margin-right: auto;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-right: -15px;
|
||||
margin-left: -15px;
|
||||
}
|
||||
|
||||
.col-md-2, .col-md-4, .col-md-6, .col-md-8, .col-md-9, .col-md-10 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
.col-md-2 { flex: 0 0 16.666667%; max-width: 16.666667%; }
|
||||
.col-md-4 { flex: 0 0 33.333333%; max-width: 33.333333%; }
|
||||
.col-md-6 { flex: 0 0 50%; max-width: 50%; }
|
||||
.col-md-8 { flex: 0 0 66.666667%; max-width: 66.666667%; }
|
||||
.col-md-9 { flex: 0 0 75%; max-width: 75%; }
|
||||
.col-md-10 { flex: 0 0 83.333333%; max-width: 83.333333%; }
|
||||
|
||||
.card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
word-wrap: break-word;
|
||||
background-color: #fff;
|
||||
background-clip: border-box;
|
||||
border: 1px solid rgba(0,0,0,.125);
|
||||
border-radius: 0.375rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.card-header {
|
||||
padding: 0.75rem 1.25rem;
|
||||
margin-bottom: 0;
|
||||
background-color: rgba(0,0,0,.03);
|
||||
border-bottom: 1px solid rgba(0,0,0,.125);
|
||||
}
|
||||
|
||||
.card-body {
|
||||
flex: 1 1 auto;
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
line-height: 1.5;
|
||||
color: #212529;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background-color: transparent;
|
||||
border: 1px solid transparent;
|
||||
padding: 0.375rem 0.75rem;
|
||||
font-size: 1rem;
|
||||
border-radius: 0.375rem;
|
||||
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: #0d6efd;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
color: #fff;
|
||||
background-color: #0b5ed7;
|
||||
border-color: #0a58ca;
|
||||
}
|
||||
|
||||
.btn-outline-primary {
|
||||
color: #0d6efd;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
|
||||
.btn-outline-primary:hover {
|
||||
color: #fff;
|
||||
background-color: #0d6efd;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
|
||||
.btn-outline-danger {
|
||||
color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.btn-outline-danger:hover {
|
||||
color: #fff;
|
||||
background-color: #dc3545;
|
||||
border-color: #dc3545;
|
||||
}
|
||||
|
||||
.btn-outline-secondary {
|
||||
color: #6c757d;
|
||||
border-color: #6c757d;
|
||||
}
|
||||
|
||||
.btn-outline-secondary:hover {
|
||||
color: #fff;
|
||||
background-color: #6c757d;
|
||||
border-color: #6c757d;
|
||||
}
|
||||
|
||||
.btn-sm {
|
||||
padding: 0.25rem 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.alert {
|
||||
position: relative;
|
||||
padding: 0.75rem 1.25rem;
|
||||
margin-bottom: 1rem;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.alert-success {
|
||||
color: #0f5132;
|
||||
background-color: #d1e7dd;
|
||||
border-color: #badbcc;
|
||||
}
|
||||
|
||||
.alert-danger {
|
||||
color: #842029;
|
||||
background-color: #f8d7da;
|
||||
border-color: #f5c2c7;
|
||||
}
|
||||
|
||||
.alert-warning {
|
||||
color: #664d03;
|
||||
background-color: #fff3cd;
|
||||
border-color: #ffecb5;
|
||||
}
|
||||
|
||||
.alert-info {
|
||||
color: #055160;
|
||||
background-color: #cff4fc;
|
||||
border-color: #b6effb;
|
||||
}
|
||||
|
||||
.badge {
|
||||
display: inline-block;
|
||||
padding: 0.35em 0.65em;
|
||||
font-size: 0.75em;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.bg-success { background-color: #198754 !important; }
|
||||
.bg-danger { background-color: #dc3545 !important; }
|
||||
.bg-warning { background-color: #ffc107 !important; }
|
||||
.bg-info { background-color: #0dcaf0 !important; }
|
||||
.bg-primary { background-color: #0d6efd !important; }
|
||||
.bg-secondary { background-color: #6c757d !important; }
|
||||
|
||||
.navbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
padding-top: 0.3125rem;
|
||||
padding-bottom: 0.3125rem;
|
||||
margin-right: 1rem;
|
||||
font-size: 1.25rem;
|
||||
color: rgba(0,0,0,.9);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding-left: 0;
|
||||
margin-bottom: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: block;
|
||||
padding: 0.5rem 1rem;
|
||||
color: #0d6efd;
|
||||
text-decoration: none;
|
||||
transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out;
|
||||
}
|
||||
|
||||
.nav-link:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
.nav-link.active {
|
||||
color: #fff;
|
||||
background-color: #0d6efd;
|
||||
}
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
height: 1rem;
|
||||
overflow: hidden;
|
||||
font-size: 0.75rem;
|
||||
background-color: #e9ecef;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
background-color: #0d6efd;
|
||||
transition: width .6s ease;
|
||||
}
|
||||
|
||||
.text-center { text-align: center !important; }
|
||||
.text-muted { color: #6c757d !important; }
|
||||
.text-primary { color: #0d6efd !important; }
|
||||
.text-success { color: #198754 !important; }
|
||||
.text-danger { color: #dc3545 !important; }
|
||||
|
||||
.mb-0 { margin-bottom: 0 !important; }
|
||||
.mb-1 { margin-bottom: 0.25rem !important; }
|
||||
.mb-2 { margin-bottom: 0.5rem !important; }
|
||||
.mb-3 { margin-bottom: 1rem !important; }
|
||||
.mb-4 { margin-bottom: 1.5rem !important; }
|
||||
.mb-5 { margin-bottom: 3rem !important; }
|
||||
|
||||
.mt-2 { margin-top: 0.5rem !important; }
|
||||
.mt-3 { margin-top: 1rem !important; }
|
||||
.mt-4 { margin-top: 1.5rem !important; }
|
||||
|
||||
.me-2 { margin-right: 0.5rem !important; }
|
||||
.ms-2 { margin-left: 0.5rem !important; }
|
||||
|
||||
.py-5 { padding-top: 3rem !important; padding-bottom: 3rem !important; }
|
||||
|
||||
.img-thumbnail {
|
||||
padding: 0.25rem;
|
||||
background-color: #fff;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 0.375rem;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.img-fluid {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.rounded {
|
||||
border-radius: 0.375rem !important;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1px solid #dee2e6 !important;
|
||||
}
|
||||
|
||||
.d-none { display: none !important; }
|
||||
|
||||
.list-unstyled {
|
||||
padding-left: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.list-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 0;
|
||||
margin-bottom: 0;
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
|
||||
.list-group-item {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 0.5rem 1rem;
|
||||
color: #212529;
|
||||
text-decoration: none;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0,0,0,.125);
|
||||
}
|
||||
|
||||
.list-group-item:first-child {
|
||||
border-top-left-radius: inherit;
|
||||
border-top-right-radius: inherit;
|
||||
}
|
||||
|
||||
.list-group-item:last-child {
|
||||
border-bottom-right-radius: inherit;
|
||||
border-bottom-left-radius: inherit;
|
||||
}
|
||||
|
||||
/* Responsive */
|
||||
@media (min-width: 768px) {
|
||||
.col-md-2, .col-md-4, .col-md-6, .col-md-8, .col-md-9, .col-md-10 {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
}
|
150
services/web_interface/chart.min.js
vendored
150
services/web_interface/chart.min.js
vendored
@ -1,150 +0,0 @@
|
||||
// Chart.js minimal pour 4NK Notariat
|
||||
window.Chart = class Chart {
|
||||
constructor(ctx, config) {
|
||||
this.ctx = ctx;
|
||||
this.config = config;
|
||||
this.destroyed = false;
|
||||
|
||||
// Créer un canvas simple si Chart.js n'est pas disponible
|
||||
this.createSimpleChart();
|
||||
}
|
||||
|
||||
createSimpleChart() {
|
||||
if (this.destroyed) return;
|
||||
|
||||
const canvas = this.ctx;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const config = this.config;
|
||||
|
||||
// Effacer le canvas
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
if (config.type === 'doughnut') {
|
||||
this.drawDoughnutChart(ctx, config);
|
||||
} else if (config.type === 'line') {
|
||||
this.drawLineChart(ctx, config);
|
||||
}
|
||||
}
|
||||
|
||||
drawDoughnutChart(ctx, config) {
|
||||
const data = config.data;
|
||||
const labels = data.labels || [];
|
||||
const values = data.datasets[0].data || [];
|
||||
const colors = data.datasets[0].backgroundColor || ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF'];
|
||||
|
||||
const canvas = this.ctx;
|
||||
const centerX = canvas.width / 2;
|
||||
const centerY = canvas.height / 2;
|
||||
const radius = Math.min(centerX, centerY) - 20;
|
||||
|
||||
const total = values.reduce((sum, val) => sum + val, 0);
|
||||
let currentAngle = 0;
|
||||
|
||||
// Dessiner les segments
|
||||
values.forEach((value, index) => {
|
||||
const sliceAngle = (value / total) * 2 * Math.PI;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(centerX, centerY);
|
||||
ctx.arc(centerX, centerY, radius, currentAngle, currentAngle + sliceAngle);
|
||||
ctx.closePath();
|
||||
ctx.fillStyle = colors[index % colors.length];
|
||||
ctx.fill();
|
||||
|
||||
currentAngle += sliceAngle;
|
||||
});
|
||||
|
||||
// Dessiner la légende
|
||||
let legendY = 20;
|
||||
labels.forEach((label, index) => {
|
||||
ctx.fillStyle = colors[index % colors.length];
|
||||
ctx.fillRect(10, legendY, 15, 15);
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.font = '12px Arial';
|
||||
ctx.fillText(label, 30, legendY + 12);
|
||||
legendY += 20;
|
||||
});
|
||||
}
|
||||
|
||||
drawLineChart(ctx, config) {
|
||||
const data = config.data;
|
||||
const labels = data.labels || [];
|
||||
const values = data.datasets[0].data || [];
|
||||
const color = data.datasets[0].borderColor || '#007bff';
|
||||
|
||||
const canvas = this.ctx;
|
||||
const padding = 40;
|
||||
const chartWidth = canvas.width - 2 * padding;
|
||||
const chartHeight = canvas.height - 2 * padding;
|
||||
|
||||
const maxValue = Math.max(...values);
|
||||
const minValue = Math.min(...values);
|
||||
const valueRange = maxValue - minValue || 1;
|
||||
|
||||
// Dessiner les axes
|
||||
ctx.strokeStyle = '#ddd';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(padding, padding);
|
||||
ctx.lineTo(padding, canvas.height - padding);
|
||||
ctx.lineTo(canvas.width - padding, canvas.height - padding);
|
||||
ctx.stroke();
|
||||
|
||||
// Dessiner la ligne
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.beginPath();
|
||||
|
||||
values.forEach((value, index) => {
|
||||
const x = padding + (index / (values.length - 1)) * chartWidth;
|
||||
const y = canvas.height - padding - ((value - minValue) / valueRange) * chartHeight;
|
||||
|
||||
if (index === 0) {
|
||||
ctx.moveTo(x, y);
|
||||
} else {
|
||||
ctx.lineTo(x, y);
|
||||
}
|
||||
});
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
// Dessiner les points
|
||||
ctx.fillStyle = color;
|
||||
values.forEach((value, index) => {
|
||||
const x = padding + (index / (values.length - 1)) * chartWidth;
|
||||
const y = canvas.height - padding - ((value - minValue) / valueRange) * chartHeight;
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(x, y, 4, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
});
|
||||
|
||||
// Dessiner les labels
|
||||
ctx.fillStyle = '#333';
|
||||
ctx.font = '10px Arial';
|
||||
ctx.textAlign = 'center';
|
||||
labels.forEach((label, index) => {
|
||||
const x = padding + (index / (values.length - 1)) * chartWidth;
|
||||
ctx.fillText(label, x, canvas.height - 10);
|
||||
});
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
if (this.ctx && this.ctx.clearRect) {
|
||||
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
if (!this.destroyed) {
|
||||
this.createSimpleChart();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Simuler les options globales
|
||||
window.Chart.defaults = {
|
||||
responsive: true,
|
||||
maintainAspectRatio: false
|
||||
};
|
25
services/web_interface/fontawesome.min.css
vendored
25
services/web_interface/fontawesome.min.css
vendored
@ -1,25 +0,0 @@
|
||||
/* Font Awesome minimal pour 4NK Notariat */
|
||||
.fas, .fa {
|
||||
font-family: "Font Awesome 5 Free";
|
||||
font-weight: 900;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
text-rendering: auto;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.fa-cloud-upload-alt:before { content: "☁"; }
|
||||
.fa-folder-open:before { content: "📁"; }
|
||||
.fa-file:before { content: "📄"; }
|
||||
.fa-file-pdf:before { content: "📕"; }
|
||||
.fa-file-alt:before { content: "📄"; }
|
||||
.fa-upload:before { content: "⬆"; }
|
||||
.fa-times:before { content: "✕"; }
|
||||
.fa-eye:before { content: "👁"; }
|
||||
.fa-search:before { content: "🔍"; }
|
||||
.fa-download:before { content: "⬇"; }
|
||||
.fa-upload:before { content: "⬆"; }
|
||||
.fa-3x { font-size: 3em; }
|
||||
.fa-4x { font-size: 4em; }
|
||||
.fa-2x { font-size: 2em; }
|
@ -1,441 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>4NK Notariat - Traitement de Documents</title>
|
||||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📄</text></svg>">
|
||||
<link href="bootstrap.min.css" rel="stylesheet">
|
||||
<link href="fontawesome.min.css" rel="stylesheet">
|
||||
<style>
|
||||
.upload-area {
|
||||
border: 2px dashed #007bff;
|
||||
border-radius: 10px;
|
||||
padding: 40px;
|
||||
text-align: center;
|
||||
background-color: #f8f9fa;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.upload-area:hover {
|
||||
border-color: #0056b3;
|
||||
background-color: #e3f2fd;
|
||||
}
|
||||
.upload-area.dragover {
|
||||
border-color: #28a745;
|
||||
background-color: #d4edda;
|
||||
}
|
||||
.document-card {
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
.document-card:hover {
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
.status-badge {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
.progress-container {
|
||||
display: none;
|
||||
}
|
||||
.analysis-section {
|
||||
display: none;
|
||||
}
|
||||
.entity-item {
|
||||
background-color: #f8f9fa;
|
||||
border-left: 4px solid #007bff;
|
||||
padding: 10px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.verification-item {
|
||||
background-color: #f8f9fa;
|
||||
border-left: 4px solid #28a745;
|
||||
padding: 10px;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.verification-item.error {
|
||||
border-left-color: #dc3545;
|
||||
}
|
||||
.verification-item.warning {
|
||||
border-left-color: #ffc107;
|
||||
}
|
||||
.sidebar {
|
||||
background-color: #f8f9fa;
|
||||
min-height: 100vh;
|
||||
}
|
||||
.main-content {
|
||||
padding: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<!-- Sidebar -->
|
||||
<div class="col-md-3 sidebar p-3">
|
||||
<h4 class="mb-4">
|
||||
<i class="fas fa-balance-scale text-primary"></i>
|
||||
4NK Notariat
|
||||
</h4>
|
||||
|
||||
<nav class="nav flex-column">
|
||||
<a class="nav-link active" href="#upload" data-section="upload">
|
||||
<i class="fas fa-upload"></i> Upload Document
|
||||
</a>
|
||||
<a class="nav-link" href="#documents" data-section="documents">
|
||||
<i class="fas fa-file-alt"></i> Documents
|
||||
</a>
|
||||
<a class="nav-link" href="#stats" data-section="stats">
|
||||
<i class="fas fa-chart-bar"></i> Statistiques
|
||||
</a>
|
||||
<a class="nav-link" href="#settings" data-section="settings">
|
||||
<i class="fas fa-cog"></i> Paramètres
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="mt-4">
|
||||
<h6>Statut du Système</h6>
|
||||
<div id="system-status">
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>API:</span>
|
||||
<span class="badge bg-success" id="api-status">Connecté</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>LLM:</span>
|
||||
<span class="badge bg-success" id="llm-status">Disponible</span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span>APIs Externes:</span>
|
||||
<span class="badge bg-success" id="external-apis-status">OK</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="col-md-9 main-content">
|
||||
<!-- Upload Section -->
|
||||
<div id="upload-section" class="content-section">
|
||||
<h2 class="mb-4">
|
||||
<i class="fas fa-upload text-primary"></i>
|
||||
Upload de Document Notarial
|
||||
</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<form id="upload-form">
|
||||
<div class="upload-area" id="upload-area">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-primary mb-3"></i>
|
||||
<h5>Glissez-déposez votre document ici</h5>
|
||||
<p class="text-muted">ou cliquez pour sélectionner un fichier</p>
|
||||
<input type="file" id="file-input" class="d-none" accept=".pdf,.jpg,.jpeg,.png,.tiff,.heic">
|
||||
<button type="button" class="btn btn-primary" onclick="document.getElementById('file-input').click()">
|
||||
<i class="fas fa-folder-open"></i> Sélectionner un fichier
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<label for="id-dossier" class="form-label">ID Dossier *</label>
|
||||
<input type="text" class="form-control" id="id-dossier" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="etude-id" class="form-label">ID Étude *</label>
|
||||
<input type="text" class="form-control" id="etude-id" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-md-6">
|
||||
<label for="utilisateur-id" class="form-label">ID Utilisateur *</label>
|
||||
<input type="text" class="form-control" id="utilisateur-id" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="type-document" class="form-label">Type de Document Attendu</label>
|
||||
<select class="form-select" id="type-document">
|
||||
<option value="">Auto-détection</option>
|
||||
<option value="acte_vente">Acte de Vente</option>
|
||||
<option value="acte_donation">Acte de Donation</option>
|
||||
<option value="acte_succession">Acte de Succession</option>
|
||||
<option value="cni">Carte d'Identité</option>
|
||||
<option value="contrat">Contrat</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-success btn-lg">
|
||||
<i class="fas fa-play"></i> Traiter le Document
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<!-- Progress -->
|
||||
<div class="progress-container mt-4">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped progress-bar-animated"
|
||||
role="progressbar" style="width: 0%"></div>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<small class="text-muted" id="progress-text">Initialisation...</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6><i class="fas fa-info-circle"></i> Informations</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h6>Formats supportés:</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><i class="fas fa-file-pdf text-danger"></i> PDF</li>
|
||||
<li><i class="fas fa-file-image text-primary"></i> JPEG, PNG</li>
|
||||
<li><i class="fas fa-file-image text-info"></i> TIFF, HEIC</li>
|
||||
</ul>
|
||||
|
||||
<h6 class="mt-3">Traitement:</h6>
|
||||
<ul class="list-unstyled">
|
||||
<li><i class="fas fa-eye"></i> OCR et extraction de texte</li>
|
||||
<li><i class="fas fa-tags"></i> Classification automatique</li>
|
||||
<li><i class="fas fa-search"></i> Extraction d'entités</li>
|
||||
<li><i class="fas fa-check-circle"></i> Vérifications externes</li>
|
||||
<li><i class="fas fa-brain"></i> Analyse LLM</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Documents Section -->
|
||||
<div id="documents-section" class="content-section" style="display: none;">
|
||||
<h2 class="mb-4">
|
||||
<i class="fas fa-file-alt text-primary"></i>
|
||||
Documents Traités
|
||||
</h2>
|
||||
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="search-documents" placeholder="Rechercher un document...">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filter-status">
|
||||
<option value="">Tous les statuts</option>
|
||||
<option value="processing">En cours</option>
|
||||
<option value="completed">Terminé</option>
|
||||
<option value="error">Erreur</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filter-type">
|
||||
<option value="">Tous les types</option>
|
||||
<option value="acte_vente">Acte de Vente</option>
|
||||
<option value="acte_donation">Acte de Donation</option>
|
||||
<option value="acte_succession">Acte de Succession</option>
|
||||
<option value="cni">Carte d'Identité</option>
|
||||
<option value="contrat">Contrat</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="documents-list">
|
||||
<!-- Documents will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Statistics Section -->
|
||||
<div id="stats-section" class="content-section" style="display: none;">
|
||||
<h2 class="mb-4">
|
||||
<i class="fas fa-chart-bar text-primary"></i>
|
||||
Statistiques
|
||||
</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-file-alt fa-2x text-primary mb-2"></i>
|
||||
<h4 id="total-documents">0</h4>
|
||||
<p class="text-muted">Documents traités</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-clock fa-2x text-warning mb-2"></i>
|
||||
<h4 id="processing-documents">0</h4>
|
||||
<p class="text-muted">En cours</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-check-circle fa-2x text-success mb-2"></i>
|
||||
<h4 id="success-rate">0%</h4>
|
||||
<p class="text-muted">Taux de réussite</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="card text-center">
|
||||
<div class="card-body">
|
||||
<i class="fas fa-stopwatch fa-2x text-info mb-2"></i>
|
||||
<h4 id="avg-time">0s</h4>
|
||||
<p class="text-muted">Temps moyen</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row mt-4">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Types de Documents</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="document-types-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Évolution Temporelle</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<canvas id="timeline-chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Settings Section -->
|
||||
<div id="settings-section" class="content-section" style="display: none;">
|
||||
<h2 class="mb-4">
|
||||
<i class="fas fa-cog text-primary"></i>
|
||||
Paramètres
|
||||
</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>Configuration API</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="api-url" class="form-label">URL de l'API</label>
|
||||
<input type="text" class="form-control" id="api-url" value="http://localhost:8000">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="llm-model" class="form-label">Modèle LLM</label>
|
||||
<select class="form-select" id="llm-model">
|
||||
<option value="llama3:8b">Llama 3 8B</option>
|
||||
<option value="mistral:7b">Mistral 7B</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="testConnection()">
|
||||
<i class="fas fa-plug"></i> Tester la Connexion
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h6>APIs Externes</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="enable-cadastre" checked>
|
||||
<label class="form-check-label" for="enable-cadastre">
|
||||
Cadastre
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="enable-georisques" checked>
|
||||
<label class="form-check-label" for="enable-georisques">
|
||||
Géorisques
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="enable-bodacc" checked>
|
||||
<label class="form-check-label" for="enable-bodacc">
|
||||
BODACC
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="enable-gel-avoirs" checked>
|
||||
<label class="form-check-label" for="enable-gel-avoirs">
|
||||
Gel des Avoirs
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Document Analysis Modal -->
|
||||
<div class="modal fade" id="analysisModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">
|
||||
<i class="fas fa-search"></i> Analyse du Document
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div id="analysis-content">
|
||||
<!-- Analysis content will be loaded here -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
|
||||
<button type="button" class="btn btn-primary" onclick="downloadReport()">
|
||||
<i class="fas fa-download"></i> Télécharger le Rapport
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="chart.min.js"></script>
|
||||
<script src="app.js"></script>
|
||||
<script>
|
||||
// Initialisation de l'application après chargement de app.js
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
if (typeof NotaryApp !== 'undefined') {
|
||||
window.notaryApp = new NotaryApp();
|
||||
} else {
|
||||
console.error('NotaryApp class not found');
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,79 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Serveur web simple pour l'interface 4NK Notariat
|
||||
"""
|
||||
import http.server
|
||||
import socketserver
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
def start_web_server(port=8080):
|
||||
"""Démarre le serveur web pour l'interface"""
|
||||
|
||||
# Répertoire de l'interface web
|
||||
web_dir = Path(__file__).parent
|
||||
|
||||
# Changement vers le répertoire web
|
||||
os.chdir(web_dir)
|
||||
|
||||
# Configuration du serveur avec gestion du favicon
|
||||
class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
def end_headers(self):
|
||||
# Ajouter des headers pour éviter le cache du favicon
|
||||
if self.path == '/favicon.ico':
|
||||
self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
|
||||
self.send_header('Pragma', 'no-cache')
|
||||
self.send_header('Expires', '0')
|
||||
super().end_headers()
|
||||
|
||||
def do_GET(self):
|
||||
try:
|
||||
# Gérer le favicon.ico
|
||||
if self.path == '/favicon.ico':
|
||||
self.send_response(200)
|
||||
self.send_header('Content-type', 'image/svg+xml')
|
||||
self.end_headers()
|
||||
favicon_svg = '''<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<text y=".9em" font-size="90">📄</text>
|
||||
</svg>'''
|
||||
self.wfile.write(favicon_svg.encode())
|
||||
return
|
||||
super().do_GET()
|
||||
except (BrokenPipeError, ConnectionResetError):
|
||||
# Ignorer les erreurs de connexion fermée par le client
|
||||
pass
|
||||
|
||||
handler = CustomHTTPRequestHandler
|
||||
|
||||
try:
|
||||
with socketserver.TCPServer(("", port), handler) as httpd:
|
||||
print(f"🌐 Interface web 4NK Notariat démarrée sur http://localhost:{port}")
|
||||
print(f"📁 Répertoire: {web_dir}")
|
||||
print("🔄 Appuyez sur Ctrl+C pour arrêter")
|
||||
print()
|
||||
|
||||
httpd.serve_forever()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n🛑 Arrêt du serveur web")
|
||||
sys.exit(0)
|
||||
except OSError as e:
|
||||
if e.errno == 98: # Address already in use
|
||||
print(f"❌ Erreur: Le port {port} est déjà utilisé")
|
||||
print(f"💡 Essayez un autre port: python start_web.py {port + 1}")
|
||||
else:
|
||||
print(f"❌ Erreur: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Port par défaut ou port spécifié en argument
|
||||
port = 8080
|
||||
if len(sys.argv) > 1:
|
||||
try:
|
||||
port = int(sys.argv[1])
|
||||
except ValueError:
|
||||
print("❌ Erreur: Le port doit être un nombre")
|
||||
sys.exit(1)
|
||||
|
||||
start_web_server(port)
|
@ -6,7 +6,7 @@ import os
|
||||
import logging
|
||||
import re
|
||||
from typing import Dict, Any, List
|
||||
from services.worker.utils.llm_client import WorkerLLMClient
|
||||
from utils.llm_client import WorkerLLMClient
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -3,7 +3,7 @@ Tâches de classification des documents
|
||||
"""
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
from services.worker.celery_app import app
|
||||
from celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -3,7 +3,7 @@ Tâches d'extraction d'entités des documents
|
||||
"""
|
||||
import logging
|
||||
from typing import Dict, Any, List
|
||||
from services.worker.celery_app import app
|
||||
from celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -3,7 +3,7 @@ Tâches d'indexation des documents
|
||||
"""
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
from services.worker.celery_app import app
|
||||
from celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -36,7 +36,7 @@ def index_document(self, doc_id: str, text: str, entities: Dict[str, Any], doc_t
|
||||
|
||||
# 1. Indexation dans AnythingLLM
|
||||
try:
|
||||
from services.worker.utils.anythingllm_client import AnythingLLMClient
|
||||
from utils.anythingllm_client import AnythingLLMClient
|
||||
anyllm_client = AnythingLLMClient()
|
||||
anyllm_result = await anyllm_client.index_document_for_actes(
|
||||
doc_id, text, entities, doc_type
|
||||
@ -48,7 +48,7 @@ def index_document(self, doc_id: str, text: str, entities: Dict[str, Any], doc_t
|
||||
|
||||
# 2. Indexation dans OpenSearch
|
||||
try:
|
||||
from services.worker.utils.opensearch_client import OpenSearchClient
|
||||
from utils.opensearch_client import OpenSearchClient
|
||||
opensearch_client = OpenSearchClient()
|
||||
opensearch_result = await opensearch_client.index_document(doc_id, {
|
||||
'text_content': text,
|
||||
@ -64,7 +64,7 @@ def index_document(self, doc_id: str, text: str, entities: Dict[str, Any], doc_t
|
||||
|
||||
# 3. Création du graphe Neo4j
|
||||
try:
|
||||
from services.worker.utils.neo4j_client import Neo4jClient
|
||||
from utils.neo4j_client import Neo4jClient
|
||||
neo4j_client = Neo4jClient()
|
||||
|
||||
# Ajout du document au graphe
|
||||
|
@ -3,7 +3,7 @@ Tâches OCR pour le traitement des documents
|
||||
"""
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
from services.worker.celery_app import app
|
||||
from celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -6,8 +6,8 @@ import time
|
||||
import logging
|
||||
from typing import Dict, Any, Optional
|
||||
from celery import current_task
|
||||
from services.worker.celery_app import app
|
||||
from services.worker.pipelines import (
|
||||
from celery_app import app
|
||||
from pipelines import (
|
||||
preprocess, ocr, classify, extract, index, checks, finalize
|
||||
)
|
||||
|
||||
|
@ -3,7 +3,7 @@ Tâches de vérification et contrôle qualité
|
||||
"""
|
||||
import logging
|
||||
from typing import Dict, Any
|
||||
from services.worker.celery_app import app
|
||||
from celery_app import app
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -36,7 +36,7 @@ def verify_document(self, doc_id: str, entities: Dict[str, Any], doc_type: str,
|
||||
# 1. Vérification des adresses via Cadastre
|
||||
if 'bien' in entities and 'adresse' in entities['bien']:
|
||||
try:
|
||||
from services.worker.utils.external_apis import ExternalAPIManager
|
||||
from utils.external_apis import ExternalAPIManager
|
||||
api_manager = ExternalAPIManager()
|
||||
address_result = await api_manager.verify_address(
|
||||
entities['bien']['adresse'],
|
||||
@ -51,7 +51,7 @@ def verify_document(self, doc_id: str, entities: Dict[str, Any], doc_type: str,
|
||||
# 2. Vérification des risques géologiques
|
||||
if 'bien' in entities and 'adresse' in entities['bien']:
|
||||
try:
|
||||
from services.worker.utils.external_apis import ExternalAPIManager
|
||||
from utils.external_apis import ExternalAPIManager
|
||||
api_manager = ExternalAPIManager()
|
||||
risks_result = await api_manager.check_geological_risks(
|
||||
entities['bien']['adresse']
|
||||
@ -64,7 +64,7 @@ def verify_document(self, doc_id: str, entities: Dict[str, Any], doc_type: str,
|
||||
# 3. Vérification des entreprises (si applicable)
|
||||
if 'vendeur' in entities and 'nom' in entities['vendeur']:
|
||||
try:
|
||||
from services.worker.utils.external_apis import ExternalAPIManager
|
||||
from utils.external_apis import ExternalAPIManager
|
||||
api_manager = ExternalAPIManager()
|
||||
company_result = await api_manager.verify_company(
|
||||
entities['vendeur']['nom']
|
||||
@ -77,7 +77,7 @@ def verify_document(self, doc_id: str, entities: Dict[str, Any], doc_type: str,
|
||||
# 4. Vérification des personnes
|
||||
if 'vendeur' in entities or 'acheteur' in entities:
|
||||
try:
|
||||
from services.worker.utils.external_apis import ExternalAPIManager
|
||||
from utils.external_apis import ExternalAPIManager
|
||||
api_manager = ExternalAPIManager()
|
||||
|
||||
# Vérification du vendeur
|
||||
|
98
start-dev.sh
98
start-dev.sh
@ -1,98 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de démarrage rapide pour l'environnement de développement 4NK_IA
|
||||
# Usage: ./start-dev.sh
|
||||
|
||||
echo "=== Démarrage de l'environnement de développement 4NK_IA ==="
|
||||
echo
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if [ ! -f "requirements-test.txt" ]; then
|
||||
echo "❌ Erreur: Ce script doit être exécuté depuis le répertoire racine du projet 4NK_IA"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Activer l'environnement virtuel Python
|
||||
echo "🐍 Activation de l'environnement virtuel Python..."
|
||||
if [ -d "venv" ]; then
|
||||
source venv/bin/activate
|
||||
echo " ✅ Environnement virtuel activé"
|
||||
else
|
||||
echo " ❌ Environnement virtuel non trouvé. Création..."
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
echo " ✅ Environnement virtuel créé et activé"
|
||||
fi
|
||||
|
||||
# Vérifier les dépendances Python
|
||||
echo "📦 Vérification des dépendances Python..."
|
||||
if python -c "import fastapi" 2>/dev/null; then
|
||||
echo " ✅ FastAPI disponible"
|
||||
else
|
||||
echo " ⚠️ FastAPI non installé. Installation..."
|
||||
pip install fastapi uvicorn pydantic
|
||||
fi
|
||||
|
||||
if python -c "import pytest" 2>/dev/null; then
|
||||
echo " ✅ pytest disponible"
|
||||
else
|
||||
echo " ⚠️ pytest non installé. Installation..."
|
||||
pip install pytest
|
||||
fi
|
||||
|
||||
# Vérifier Docker
|
||||
echo "🐳 Vérification de Docker..."
|
||||
if command -v docker >/dev/null 2>&1; then
|
||||
echo " ✅ Docker disponible"
|
||||
if docker ps >/dev/null 2>&1; then
|
||||
echo " ✅ Docker fonctionne"
|
||||
else
|
||||
echo " ⚠️ Docker installé mais non démarré"
|
||||
echo " 💡 Démarrez Docker Desktop et activez l'intégration WSL2"
|
||||
fi
|
||||
else
|
||||
echo " ❌ Docker non installé"
|
||||
echo " 💡 Installez Docker Desktop et activez l'intégration WSL2"
|
||||
fi
|
||||
|
||||
# Vérifier la configuration Git
|
||||
echo "🔑 Vérification de la configuration Git..."
|
||||
if git config --global user.name >/dev/null 2>&1; then
|
||||
echo " ✅ Git configuré: $(git config --global user.name) <$(git config --global user.email)>"
|
||||
else
|
||||
echo " ❌ Git non configuré"
|
||||
fi
|
||||
|
||||
# Vérifier SSH
|
||||
echo "🔐 Vérification de la configuration SSH..."
|
||||
if [ -f ~/.ssh/id_ed25519 ]; then
|
||||
echo " ✅ Clé SSH trouvée"
|
||||
if ssh -o ConnectTimeout=5 -o BatchMode=yes -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
|
||||
echo " ✅ Connexion SSH à git.4nkweb.com réussie"
|
||||
else
|
||||
echo " ⚠️ Connexion SSH à git.4nkweb.com échouée"
|
||||
echo " 💡 Vérifiez que votre clé SSH est ajoutée à git.4nkweb.com"
|
||||
fi
|
||||
else
|
||||
echo " ❌ Clé SSH non trouvée"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "=== Résumé de l'environnement ==="
|
||||
echo "📁 Répertoire: $(pwd)"
|
||||
echo "🐍 Python: $(python --version 2>/dev/null || echo 'Non disponible')"
|
||||
echo "📦 pip: $(pip --version 2>/dev/null || echo 'Non disponible')"
|
||||
echo "🔑 Git: $(git --version 2>/dev/null || echo 'Non disponible')"
|
||||
echo "🐳 Docker: $(docker --version 2>/dev/null || echo 'Non disponible')"
|
||||
|
||||
echo
|
||||
echo "=== Commandes utiles ==="
|
||||
echo "🚀 Démarrer l'API: uvicorn services.host_api.app:app --reload --host 0.0.0.0 --port 8000"
|
||||
echo "🧪 Lancer les tests: pytest"
|
||||
echo "🐳 Démarrer Docker: make up"
|
||||
echo "📊 Voir les logs: make logs"
|
||||
echo "🛑 Arrêter Docker: make down"
|
||||
|
||||
echo
|
||||
echo "✅ Environnement de développement prêt !"
|
||||
echo "💡 Utilisez 'source venv/bin/activate' pour activer l'environnement virtuel"
|
111
start-stack.sh
111
start-stack.sh
@ -1,111 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de démarrage de la stack 4NK_IA_back
|
||||
# Usage: ./start-stack.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "🚀 Démarrage de la stack 4NK_IA_back..."
|
||||
|
||||
# Vérifier que nous sommes dans le bon répertoire
|
||||
if [ ! -f "requirements-test.txt" ]; then
|
||||
echo "❌ Erreur: Ce script doit être exécuté depuis le répertoire racine du projet 4NK_IA_back"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Vérifier Docker
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "❌ Docker n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker ps >/dev/null 2>&1; then
|
||||
echo "❌ Docker n'est pas démarré"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Aller dans le répertoire infra
|
||||
cd infra
|
||||
|
||||
# Créer le fichier .env s'il n'existe pas
|
||||
if [ ! -f .env ]; then
|
||||
echo "📝 Création du fichier .env..."
|
||||
cat > .env << 'EOF'
|
||||
# Configuration de l'environnement 4NK_IA_back
|
||||
# Fichier généré automatiquement pour le démarrage de la stack
|
||||
|
||||
# Configuration générale
|
||||
TZ=Europe/Paris
|
||||
PUID=1000
|
||||
PGID=1000
|
||||
|
||||
# Configuration PostgreSQL
|
||||
POSTGRES_USER=notariat
|
||||
POSTGRES_PASSWORD=notariat_pwd
|
||||
POSTGRES_DB=notariat
|
||||
|
||||
# Configuration MinIO
|
||||
MINIO_ROOT_USER=minio
|
||||
MINIO_ROOT_PASSWORD=minio_pwd
|
||||
MINIO_BUCKET=ingest
|
||||
MINIO_ENDPOINT=minio:9000
|
||||
|
||||
# Configuration Neo4j
|
||||
NEO4J_AUTH=neo4j/neo4j_pwd
|
||||
|
||||
# Configuration OpenSearch
|
||||
OPENSEARCH_PASSWORD=opensearch_pwd
|
||||
|
||||
# Configuration AnythingLLM
|
||||
ANYLLM_BASE_URL=http://anythingsqlite:3001
|
||||
ANYLLM_API_KEY=notariat_api_key_2025
|
||||
ANYLLM_WORKSPACE_NORMES=workspace_normes
|
||||
ANYLLM_WORKSPACE_TRAMES=workspace_trames
|
||||
ANYLLM_WORKSPACE_ACTES=workspace_actes
|
||||
|
||||
# Configuration Ollama
|
||||
OLLAMA_BASE_URL=http://ollama:11434
|
||||
|
||||
# Configuration des URLs externes (pour les tests)
|
||||
EXTERNAL_ANYLLM_BASE_URL=http://localhost:3001
|
||||
EXTERNAL_OLLAMA_BASE_URL=http://localhost:11434
|
||||
EOF
|
||||
echo "✅ Fichier .env créé"
|
||||
else
|
||||
echo "✅ Fichier .env existe déjà"
|
||||
fi
|
||||
|
||||
# Démarrer les services
|
||||
echo "🐳 Démarrage des services Docker..."
|
||||
docker compose up -d
|
||||
|
||||
# Attendre que les services soient prêts
|
||||
echo "⏳ Attente du démarrage des services..."
|
||||
sleep 15
|
||||
|
||||
# Vérifier l'API
|
||||
echo "🔍 Vérification de l'API..."
|
||||
if curl -s http://localhost:8000/api/health > /dev/null; then
|
||||
echo "✅ API accessible sur http://localhost:8000"
|
||||
else
|
||||
echo "⚠️ API non accessible, vérifiez les logs avec: docker compose logs host-api"
|
||||
fi
|
||||
|
||||
# Afficher le statut
|
||||
echo "📊 Statut des services:"
|
||||
docker compose ps
|
||||
|
||||
echo ""
|
||||
echo "🎉 Stack 4NK_IA_back démarrée !"
|
||||
echo ""
|
||||
echo "📋 Services disponibles:"
|
||||
echo " • API Notariale: http://localhost:8000"
|
||||
echo " • Documentation API: http://localhost:8000/docs"
|
||||
echo " • MinIO Console: http://localhost:9001"
|
||||
echo " • PostgreSQL: localhost:5432"
|
||||
echo " • Redis: localhost:6379"
|
||||
echo ""
|
||||
echo "🔧 Commandes utiles:"
|
||||
echo " • Voir les logs: docker compose logs -f"
|
||||
echo " • Arrêter: docker compose down"
|
||||
echo " • Redémarrer: docker compose restart"
|
@ -1,313 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚀 Démarrage du Système Notarial 4NK"
|
||||
echo "======================================"
|
||||
echo
|
||||
|
||||
# Couleurs pour les messages
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
# Fonction pour afficher les messages colorés
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Vérification des prérequis
|
||||
check_prerequisites() {
|
||||
print_status "Vérification des prérequis..."
|
||||
|
||||
# Python
|
||||
if ! command -v python3 &> /dev/null; then
|
||||
print_error "Python 3 n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docker
|
||||
if ! command -v docker &> /dev/null; then
|
||||
print_error "Docker n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Docker Compose
|
||||
if ! command -v docker-compose &> /dev/null; then
|
||||
print_error "Docker Compose n'est pas installé"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Tesseract
|
||||
if ! command -v tesseract &> /dev/null; then
|
||||
print_warning "Tesseract OCR n'est pas installé"
|
||||
print_status "Installation de Tesseract..."
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y tesseract-ocr tesseract-ocr-fra
|
||||
fi
|
||||
|
||||
print_success "Prérequis vérifiés"
|
||||
}
|
||||
|
||||
# Configuration de l'environnement
|
||||
setup_environment() {
|
||||
print_status "Configuration de l'environnement..."
|
||||
|
||||
# Création de l'environnement virtuel si nécessaire
|
||||
if [ ! -d "venv" ]; then
|
||||
print_status "Création de l'environnement virtuel Python..."
|
||||
python3 -m venv venv
|
||||
fi
|
||||
|
||||
# Activation de l'environnement virtuel
|
||||
source venv/bin/activate
|
||||
|
||||
# Installation des dépendances Python
|
||||
print_status "Installation des dépendances Python..."
|
||||
pip install --upgrade pip
|
||||
pip install -r docker/host-api/requirements.txt
|
||||
|
||||
# Configuration des variables d'environnement
|
||||
if [ ! -f "infra/.env" ]; then
|
||||
print_status "Création du fichier de configuration..."
|
||||
cp infra/.env.example infra/.env
|
||||
print_warning "Veuillez éditer infra/.env avec vos paramètres"
|
||||
fi
|
||||
|
||||
print_success "Environnement configuré"
|
||||
}
|
||||
|
||||
# Démarrage des services Docker
|
||||
start_docker_services() {
|
||||
print_status "Démarrage des services Docker..."
|
||||
|
||||
cd infra
|
||||
|
||||
# Pull des images
|
||||
print_status "Téléchargement des images Docker..."
|
||||
docker-compose pull
|
||||
|
||||
# Démarrage des services de base
|
||||
print_status "Démarrage des services de base..."
|
||||
docker-compose up -d postgres redis minio ollama anythingsqlite
|
||||
|
||||
# Attente que les services soient prêts
|
||||
print_status "Attente que les services soient prêts..."
|
||||
sleep 10
|
||||
|
||||
# Vérification des services
|
||||
print_status "Vérification des services..."
|
||||
|
||||
# PostgreSQL
|
||||
if docker-compose exec -T postgres pg_isready -U notariat &> /dev/null; then
|
||||
print_success "PostgreSQL est prêt"
|
||||
else
|
||||
print_error "PostgreSQL n'est pas accessible"
|
||||
fi
|
||||
|
||||
# Redis
|
||||
if docker-compose exec -T redis redis-cli ping &> /dev/null; then
|
||||
print_success "Redis est prêt"
|
||||
else
|
||||
print_error "Redis n'est pas accessible"
|
||||
fi
|
||||
|
||||
# MinIO
|
||||
if curl -s http://localhost:9000/minio/health/live &> /dev/null; then
|
||||
print_success "MinIO est prêt"
|
||||
else
|
||||
print_warning "MinIO n'est pas accessible (normal si pas encore démarré)"
|
||||
fi
|
||||
|
||||
# Ollama
|
||||
if curl -s http://localhost:11434/api/tags &> /dev/null; then
|
||||
print_success "Ollama est prêt"
|
||||
else
|
||||
print_warning "Ollama n'est pas accessible"
|
||||
fi
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
# Configuration d'Ollama
|
||||
setup_ollama() {
|
||||
print_status "Configuration d'Ollama..."
|
||||
|
||||
# Attente qu'Ollama soit prêt
|
||||
sleep 5
|
||||
|
||||
# Téléchargement des modèles
|
||||
print_status "Téléchargement des modèles LLM..."
|
||||
|
||||
# Llama 3 8B
|
||||
print_status "Téléchargement de Llama 3 8B..."
|
||||
curl -s http://localhost:11434/api/pull -d '{"name":"llama3:8b"}' &
|
||||
|
||||
# Mistral 7B
|
||||
print_status "Téléchargement de Mistral 7B..."
|
||||
curl -s http://localhost:11434/api/pull -d '{"name":"mistral:7b"}' &
|
||||
|
||||
print_warning "Les modèles LLM sont en cours de téléchargement en arrière-plan"
|
||||
print_warning "Cela peut prendre plusieurs minutes selon votre connexion"
|
||||
}
|
||||
|
||||
# Démarrage de l'API
|
||||
start_api() {
|
||||
print_status "Démarrage de l'API Notariale..."
|
||||
|
||||
cd services/host_api
|
||||
|
||||
# Démarrage en arrière-plan
|
||||
nohup uvicorn app:app --host 0.0.0.0 --port 8000 --reload > ../../logs/api.log 2>&1 &
|
||||
API_PID=$!
|
||||
echo $API_PID > ../../logs/api.pid
|
||||
|
||||
# Attente que l'API soit prête
|
||||
print_status "Attente que l'API soit prête..."
|
||||
sleep 5
|
||||
|
||||
# Test de l'API
|
||||
if curl -s http://localhost:8000/api/health &> /dev/null; then
|
||||
print_success "API Notariale démarrée sur http://localhost:8000"
|
||||
else
|
||||
print_error "L'API n'est pas accessible"
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
}
|
||||
|
||||
# Démarrage de l'interface web
|
||||
start_web_interface() {
|
||||
print_status "Démarrage de l'interface web..."
|
||||
|
||||
cd services/web_interface
|
||||
|
||||
# Démarrage en arrière-plan
|
||||
nohup python start_web.py 8080 > ../../logs/web.log 2>&1 &
|
||||
WEB_PID=$!
|
||||
echo $WEB_PID > ../../logs/web.pid
|
||||
|
||||
# Attente que l'interface soit prête
|
||||
sleep 3
|
||||
|
||||
if curl -s http://localhost:8080 &> /dev/null; then
|
||||
print_success "Interface web démarrée sur http://localhost:8080"
|
||||
else
|
||||
print_error "L'interface web n'est pas accessible"
|
||||
fi
|
||||
|
||||
cd ../..
|
||||
}
|
||||
|
||||
# Création des répertoires de logs
|
||||
create_log_directories() {
|
||||
print_status "Création des répertoires de logs..."
|
||||
mkdir -p logs
|
||||
print_success "Répertoires de logs créés"
|
||||
}
|
||||
|
||||
# Affichage du statut final
|
||||
show_final_status() {
|
||||
echo
|
||||
echo "🎉 Système Notarial 4NK démarré avec succès!"
|
||||
echo "============================================="
|
||||
echo
|
||||
echo "📊 Services disponibles:"
|
||||
echo " • API Notariale: http://localhost:8000"
|
||||
echo " • Interface Web: http://localhost:8080"
|
||||
echo " • Documentation API: http://localhost:8000/docs"
|
||||
echo " • MinIO Console: http://localhost:9001"
|
||||
echo " • Ollama: http://localhost:11434"
|
||||
echo
|
||||
echo "📁 Fichiers de logs:"
|
||||
echo " • API: logs/api.log"
|
||||
echo " • Interface Web: logs/web.log"
|
||||
echo
|
||||
echo "🔧 Commandes utiles:"
|
||||
echo " • Arrêter le système: ./stop_notary_system.sh"
|
||||
echo " • Voir les logs: tail -f logs/api.log"
|
||||
echo " • Redémarrer l'API: kill \$(cat logs/api.pid) && ./start_notary_system.sh"
|
||||
echo
|
||||
echo "📖 Documentation: docs/API-NOTARIALE.md"
|
||||
echo
|
||||
}
|
||||
|
||||
# Fonction principale
|
||||
main() {
|
||||
echo "Démarrage du système à $(date)"
|
||||
echo
|
||||
|
||||
# Vérification des prérequis
|
||||
check_prerequisites
|
||||
|
||||
# Configuration de l'environnement
|
||||
setup_environment
|
||||
|
||||
# Création des répertoires
|
||||
create_log_directories
|
||||
|
||||
# Démarrage des services Docker
|
||||
start_docker_services
|
||||
|
||||
# Configuration d'Ollama
|
||||
setup_ollama
|
||||
|
||||
# Démarrage de l'API
|
||||
start_api
|
||||
|
||||
# Démarrage de l'interface web
|
||||
start_web_interface
|
||||
|
||||
# Affichage du statut final
|
||||
show_final_status
|
||||
}
|
||||
|
||||
# Gestion des signaux
|
||||
cleanup() {
|
||||
echo
|
||||
print_warning "Arrêt du système..."
|
||||
|
||||
# Arrêt de l'API
|
||||
if [ -f "logs/api.pid" ]; then
|
||||
API_PID=$(cat logs/api.pid)
|
||||
if kill -0 $API_PID 2>/dev/null; then
|
||||
kill $API_PID
|
||||
print_status "API arrêtée"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arrêt de l'interface web
|
||||
if [ -f "logs/web.pid" ]; then
|
||||
WEB_PID=$(cat logs/web.pid)
|
||||
if kill -0 $WEB_PID 2>/dev/null; then
|
||||
kill $WEB_PID
|
||||
print_status "Interface web arrêtée"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Arrêt des services Docker
|
||||
cd infra
|
||||
docker-compose down
|
||||
cd ..
|
||||
|
||||
print_success "Système arrêté"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Capture des signaux d'arrêt
|
||||
trap cleanup SIGINT SIGTERM
|
||||
|
||||
# Exécution du script principal
|
||||
main "$@"
|
@ -1,160 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🛑 Arrêt du Système Notarial 4NK"
|
||||
echo "================================="
|
||||
echo
|
||||
|
||||
# Couleurs pour les messages
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Arrêt de l'API
|
||||
stop_api() {
|
||||
print_status "Arrêt de l'API Notariale..."
|
||||
|
||||
if [ -f "logs/api.pid" ]; then
|
||||
API_PID=$(cat logs/api.pid)
|
||||
if kill -0 $API_PID 2>/dev/null; then
|
||||
kill $API_PID
|
||||
print_success "API arrêtée (PID: $API_PID)"
|
||||
else
|
||||
print_warning "API déjà arrêtée"
|
||||
fi
|
||||
rm -f logs/api.pid
|
||||
else
|
||||
print_warning "Fichier PID de l'API non trouvé"
|
||||
fi
|
||||
}
|
||||
|
||||
# Arrêt de l'interface web
|
||||
stop_web_interface() {
|
||||
print_status "Arrêt de l'interface web..."
|
||||
|
||||
if [ -f "logs/web.pid" ]; then
|
||||
WEB_PID=$(cat logs/web.pid)
|
||||
if kill -0 $WEB_PID 2>/dev/null; then
|
||||
kill $WEB_PID
|
||||
print_success "Interface web arrêtée (PID: $WEB_PID)"
|
||||
else
|
||||
print_warning "Interface web déjà arrêtée"
|
||||
fi
|
||||
rm -f logs/web.pid
|
||||
else
|
||||
print_warning "Fichier PID de l'interface web non trouvé"
|
||||
fi
|
||||
}
|
||||
|
||||
# Arrêt des services Docker
|
||||
stop_docker_services() {
|
||||
print_status "Arrêt des services Docker..."
|
||||
|
||||
cd infra
|
||||
|
||||
# Arrêt des services
|
||||
docker-compose down
|
||||
|
||||
print_success "Services Docker arrêtés"
|
||||
|
||||
cd ..
|
||||
}
|
||||
|
||||
# Nettoyage des processus orphelins
|
||||
cleanup_orphaned_processes() {
|
||||
print_status "Nettoyage des processus orphelins..."
|
||||
|
||||
# Recherche et arrêt des processus uvicorn
|
||||
UVICORN_PIDS=$(pgrep -f "uvicorn.*app:app")
|
||||
if [ ! -z "$UVICORN_PIDS" ]; then
|
||||
echo $UVICORN_PIDS | xargs kill
|
||||
print_success "Processus uvicorn orphelins arrêtés"
|
||||
fi
|
||||
|
||||
# Recherche et arrêt des processus Python de l'interface web
|
||||
WEB_PIDS=$(pgrep -f "start_web.py")
|
||||
if [ ! -z "$WEB_PIDS" ]; then
|
||||
echo $WEB_PIDS | xargs kill
|
||||
print_success "Processus interface web orphelins arrêtés"
|
||||
fi
|
||||
}
|
||||
|
||||
# Affichage du statut final
|
||||
show_final_status() {
|
||||
echo
|
||||
echo "✅ Système Notarial 4NK arrêté"
|
||||
echo "==============================="
|
||||
echo
|
||||
echo "📊 Statut des services:"
|
||||
|
||||
# Vérification de l'API
|
||||
if curl -s http://localhost:8000/api/health &> /dev/null; then
|
||||
echo " • API: ${RED}Encore actif${NC}"
|
||||
else
|
||||
echo " • API: ${GREEN}Arrêté${NC}"
|
||||
fi
|
||||
|
||||
# Vérification de l'interface web
|
||||
if curl -s http://localhost:8080 &> /dev/null; then
|
||||
echo " • Interface Web: ${RED}Encore actif${NC}"
|
||||
else
|
||||
echo " • Interface Web: ${GREEN}Arrêté${NC}"
|
||||
fi
|
||||
|
||||
# Vérification des services Docker
|
||||
cd infra
|
||||
if docker-compose ps | grep -q "Up"; then
|
||||
echo " • Services Docker: ${RED}Encore actifs${NC}"
|
||||
else
|
||||
echo " • Services Docker: ${GREEN}Arrêtés${NC}"
|
||||
fi
|
||||
cd ..
|
||||
|
||||
echo
|
||||
echo "🔧 Pour redémarrer: ./start_notary_system.sh"
|
||||
echo
|
||||
}
|
||||
|
||||
# Fonction principale
|
||||
main() {
|
||||
echo "Arrêt du système à $(date)"
|
||||
echo
|
||||
|
||||
# Arrêt de l'API
|
||||
stop_api
|
||||
|
||||
# Arrêt de l'interface web
|
||||
stop_web_interface
|
||||
|
||||
# Arrêt des services Docker
|
||||
stop_docker_services
|
||||
|
||||
# Nettoyage des processus orphelins
|
||||
cleanup_orphaned_processes
|
||||
|
||||
# Attente pour que les processus se terminent
|
||||
sleep 2
|
||||
|
||||
# Affichage du statut final
|
||||
show_final_status
|
||||
}
|
||||
|
||||
# Exécution du script principal
|
||||
main "$@"
|
@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "=== Test du pipeline notarial simplifié ==="
|
||||
|
||||
# Test de santé de l'API
|
||||
echo "1. Test de santé de l'API..."
|
||||
curl -s http://localhost:8000/api/health | jq . || echo "API non accessible"
|
||||
|
||||
echo ""
|
||||
echo "2. Test de l'endpoint racine..."
|
||||
curl -s http://localhost:8000/ | jq . || echo "Endpoint racine non accessible"
|
||||
|
||||
echo ""
|
||||
echo "3. Test de liste des documents..."
|
||||
curl -s http://localhost:8000/api/documents | jq . || echo "Liste des documents non accessible"
|
||||
|
||||
echo ""
|
||||
echo "=== Tests terminés ==="
|
@ -1,76 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Script de test de la configuration SSH pour 4NK_IA
|
||||
# Usage: ./test-ssh-connection.sh
|
||||
|
||||
echo "=== Test de la configuration SSH ==="
|
||||
echo
|
||||
|
||||
# Vérifier la présence des clés SSH
|
||||
echo "1. Vérification des clés SSH :"
|
||||
if [ -f ~/.ssh/id_ed25519 ]; then
|
||||
echo " ✅ Clé privée trouvée : ~/.ssh/id_ed25519"
|
||||
else
|
||||
echo " ❌ Clé privée manquante : ~/.ssh/id_ed25519"
|
||||
fi
|
||||
|
||||
if [ -f ~/.ssh/id_ed25519.pub ]; then
|
||||
echo " ✅ Clé publique trouvée : ~/.ssh/id_ed25519.pub"
|
||||
echo " 📋 Clé publique :"
|
||||
cat ~/.ssh/id_ed25519.pub | sed 's/^/ /'
|
||||
else
|
||||
echo " ❌ Clé publique manquante : ~/.ssh/id_ed25519.pub"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# Vérifier la configuration SSH
|
||||
echo "2. Vérification de la configuration SSH :"
|
||||
if [ -f ~/.ssh/config ]; then
|
||||
echo " ✅ Fichier de configuration SSH trouvé"
|
||||
echo " 📋 Configuration :"
|
||||
cat ~/.ssh/config | sed 's/^/ /'
|
||||
else
|
||||
echo " ❌ Fichier de configuration SSH manquant"
|
||||
fi
|
||||
|
||||
echo
|
||||
|
||||
# Vérifier la configuration Git
|
||||
echo "3. Vérification de la configuration Git :"
|
||||
echo " 📋 Configuration Git :"
|
||||
git config --global --list | grep -E "(user\.|url\.|init\.)" | sed 's/^/ /'
|
||||
|
||||
echo
|
||||
|
||||
# Tester les connexions SSH
|
||||
echo "4. Test des connexions SSH :"
|
||||
|
||||
echo " 🔍 Test de connexion à git.4nkweb.com :"
|
||||
if ssh -o ConnectTimeout=10 -o BatchMode=yes -T git@git.4nkweb.com 2>&1 | grep -q "successfully authenticated"; then
|
||||
echo " ✅ Connexion SSH réussie à git.4nkweb.com"
|
||||
elif ssh -o ConnectTimeout=10 -o BatchMode=yes -T git@git.4nkweb.com 2>&1 | grep -q "Permission denied"; then
|
||||
echo " ⚠️ Clé SSH non autorisée sur git.4nkweb.com"
|
||||
echo " 💡 Ajoutez votre clé publique dans les paramètres SSH de votre compte"
|
||||
else
|
||||
echo " ❌ Impossible de se connecter à git.4nkweb.com"
|
||||
fi
|
||||
|
||||
echo " 🔍 GitHub non configuré (inutile pour ce projet)"
|
||||
|
||||
echo
|
||||
|
||||
# Instructions pour ajouter les clés
|
||||
echo "5. Instructions pour ajouter votre clé SSH :"
|
||||
echo " 📋 Votre clé publique SSH :"
|
||||
cat ~/.ssh/id_ed25519.pub
|
||||
echo
|
||||
echo " 🔗 git.4nkweb.com :"
|
||||
echo " 1. Connectez-vous à git.4nkweb.com"
|
||||
echo " 2. Allez dans Settings > SSH Keys"
|
||||
echo " 3. Ajoutez la clé ci-dessus"
|
||||
echo
|
||||
echo " 🔗 GitHub : Non nécessaire pour ce projet"
|
||||
echo
|
||||
|
||||
echo "=== Fin du test ==="
|
Loading…
x
Reference in New Issue
Block a user