Files
Catalogue_pos_nearle/run_project.py

156 lines
5.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""
Unified Single-Command Project Launcher for Brand Catalog Product LLM & RAG Intelligence Engine.
Usage:
python run_project.py
What this script automates:
1. Checks & launches PostgreSQL via Docker Compose (`docker compose up -d`).
2. Starts FastAPI backend server on http://localhost:8000 (with background auto-seeding).
3. Starts Vite frontend dev server on http://localhost:5173 (or serves static dist).
4. Keeps both servers running concurrently with instant hot-reloading & single Ctrl+C exit.
"""
import os
import sys
import time
import subprocess
import signal
from pathlib import Path
if sys.platform == "win32":
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
ROOT_DIR = Path(__file__).resolve().parent
BACKEND_DIR = ROOT_DIR / "backend"
FRONTEND_DIR = ROOT_DIR / "frontend"
VENV_PYTHON = BACKEND_DIR / "venv" / "Scripts" / "python.exe"
if not VENV_PYTHON.exists():
VENV_PYTHON = Path(sys.executable)
def print_banner():
print("\033[96m" + "=" * 70)
print(" 🚀 BRAND CATALOG PRODUCT LLM & RAG INTELLIGENCE ENGINE")
print("=" * 70 + "\033[0m")
import shutil
def start_docker():
print("\n📦 Checking PostgreSQL Docker container...")
compose_file = ROOT_DIR / "docker-compose.yml"
if not compose_file.exists():
compose_file = BACKEND_DIR / "docker-compose.yml"
if compose_file.exists():
try:
res = subprocess.run(["docker", "compose", "-f", str(compose_file), "up", "-d"], capture_output=True, text=True)
if res.returncode == 0:
print("✅ PostgreSQL container is running on port 5432 (pgvector ready).")
else:
print("⚠️ Docker notice:", res.stderr.strip() or "Ensure Docker Desktop is running if using Docker Postgres.")
except Exception as e:
print(f"⚠️ Docker check skipped: {e}")
def start_ollama():
print("\n🦙 Checking Ollama LLM service...")
import urllib.request
try:
req = urllib.request.urlopen("http://localhost:11434/api/tags", timeout=2)
if req.getcode() == 200:
print("✅ Ollama LLM server is running on http://localhost:11434.")
return None
except Exception:
pass
if not shutil.which("ollama"):
print("ℹ️ Ollama CLI not installed/found. Backend will use catalog-grounded fallback responses.")
return None
try:
p = subprocess.Popen(["ollama", "serve"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print("🚀 Automatically launched Ollama LLM server background process.")
return p
except Exception as e:
print(f"⚠️ Ollama auto-launch note: {e} (App will use catalog grounded fallback).")
return None
def main():
print_banner()
start_docker()
p_ollama = start_ollama()
processes = []
if p_ollama:
processes.append(p_ollama)
try:
# 1. Start Backend FastAPI Uvicorn
print("\n⚡ Starting Backend FastAPI Server (http://localhost:8000)...")
backend_cmd = [
str(VENV_PYTHON), "-m", "uvicorn", "app.main:app",
"--reload", "--host", "0.0.0.0", "--port", "8000"
]
env_backend = os.environ.copy()
env_backend["PYTHONPATH"] = str(BACKEND_DIR)
env_backend["PYTHONIOENCODING"] = "utf-8"
p_backend = subprocess.Popen(
backend_cmd, cwd=str(BACKEND_DIR), env=env_backend
)
processes.append(p_backend)
# 2. Start Frontend Vite Dev Server
print("🎨 Starting Frontend Vite Server (http://localhost:5173)...")
npm_cmd = "npm.cmd" if sys.platform == "win32" else "npm"
p_frontend = subprocess.Popen(
[npm_cmd, "run", "dev"], cwd=str(FRONTEND_DIR), shell=(sys.platform == "win32")
)
processes.append(p_frontend)
print("\n\033[92m" + "=" * 70)
print(" 🎉 APPLICATION IS LIVE AND READY!")
print("=" * 70 + "\033[0m")
print(" 👉 Web App UI: \033[94mhttp://localhost:5173\033[0m")
print(" 👉 Backend API: \033[94mhttp://localhost:8000\033[0m")
print(" 👉 API Docs: \033[94mhttp://localhost:8000/docs\033[0m")
print(" 👉 System Status: \033[94mhttp://localhost:8000/api/system/status\033[0m")
print("=" * 70)
print(" (Press Ctrl+C to stop all servers gracefully)\n")
# Monitor core servers (backend & frontend)
core_processes = [p_backend, p_frontend]
while True:
time.sleep(1)
for p in core_processes:
if p.poll() is not None:
print(f"⚠️ Core process PID {p.pid} exited with code {p.returncode}")
return
except KeyboardInterrupt:
print("\n🛑 Stopping all services...")
finally:
for p in processes:
try:
p.terminate()
p.wait(timeout=3)
except Exception:
try:
p.kill()
except Exception:
pass
print("👋 Goodbye! All processes terminated.")
if __name__ == "__main__":
main()