# TAU-RAG dev helpers # ------------------------------------------------------------------- .PHONY: help test demo bench ab dashboard build-slim build-full \ run-slim run-full stop clean install install-full \ build-prod run-prod prod-up prod-down prod-logs prod-ps \ k8s-apply k8s-status k8s-logs k8s-delete \ lint format security-scan help: @echo "TAU-RAG make targets:" @echo "" @echo "DEV / LOCAL (no Docker needed):" @echo " make test — run pytest in isolation" @echo " make demo — legal chunks + synth labels demo" @echo " make bench — eval --demo benchmark" @echo " make ab — A/B: no_llm vs hebrew_dense" @echo " make dashboard — open the latest dashboard HTML" @echo " make run-local — uvicorn on :8000 (no_llm)" @echo " make run-local-full — uvicorn on :8001 (hebrew_dense)" @echo "" @echo "PRODUCTION (needs Docker Desktop or OrbStack):" @echo " make build-slim — docker build (~200MB)" @echo " make build-full — docker build (~3GB, AlephBERT)" @echo " make run-slim — container on :8000" @echo " make run-full — container on :8001" @echo " make stop — stop all tau-rag containers" @echo " make build-from-tmp — build from /tmp (bypasses iCloud)" @echo "" @echo "DEPS:" @echo " make install — pip install minimal deps" @echo " make install-full — pip install + torch + faiss + ST" test: bash run_tests.sh demo: python3 run.py tau_rag.examples.demo_legal_chunks_and_synth bench: python3 run.py tau_rag.api.cli eval --demo --per-doc 2 ab: python3 run.py tau_rag.examples.demo_ab_comparison dashboard: @test -f runtime/ab_report.html || make ab @case $$(uname) in \ Darwin) open runtime/ab_report.html ;; \ Linux) xdg-open runtime/ab_report.html ;; \ esac install: pip3 install -e ".[api,bm25,test]" install-full: pip3 install -e ".[all]" docker-check: @docker info >/dev/null 2>&1 || ( \ echo "❌ Docker daemon not available."; \ echo ""; \ echo "Docker NOT installed? Try one of these lighter alternatives:"; \ echo " brew install --cask docker # Docker Desktop (the classic)"; \ echo " brew install orbstack # Mac-native, much lighter"; \ echo " brew install colima # minimal CLI-only"; \ echo ""; \ echo "Docker installed but not running?"; \ echo " macOS: open -a 'Docker Desktop' (or 'OrbStack')"; \ echo " linux: sudo systemctl start docker"; \ echo ""; \ echo "💡 Don't want Docker at all? Use: make run-local"; \ exit 1 ) # Run the FastAPI server natively (no Docker). Good for dev / quick tests. run-local: check-uvicorn @mkdir -p runtime @echo "🚀 Starting tau-rag on http://localhost:8000 (preset=$${TAU_RAG_PRESET:-no_llm})" @echo " Open browser: http://localhost:8000/ · Docs: http://localhost:8000/docs" @echo " Ctrl+C to stop." TAU_RAG_PRESET=$${TAU_RAG_PRESET:-no_llm} \ python3 -c "import sys; sys.path.insert(0,'..'); \ from tau_rag.api.fastapi_app import app; \ import uvicorn; uvicorn.run(app, host='0.0.0.0', port=8000)" # Dev server with auto-reload on code changes. run-local-dev: check-uvicorn @mkdir -p runtime @echo "🔧 Dev mode (auto-reload) on http://localhost:8000" TAU_RAG_PRESET=$${TAU_RAG_PRESET:-no_llm} PYTHONPATH=.. \ uvicorn tau_rag.api.fastapi_app:app --host 0.0.0.0 --port 8000 --reload check-uvicorn: @python3 -c "import uvicorn, fastapi" 2>/dev/null || ( \ echo "❌ uvicorn/fastapi not installed."; \ echo " pip3 install 'fastapi>=0.111' 'uvicorn[standard]>=0.29'"; \ exit 1 ) run-local-full: check-uvicorn @mkdir -p runtime @echo "🚀 Starting tau-rag (AlephBERT) on http://localhost:8001" TAU_RAG_PRESET=hebrew_dense \ python3 -c "import sys; sys.path.insert(0,'..'); \ from tau_rag.api.fastapi_app import app; \ import uvicorn; uvicorn.run(app, host='0.0.0.0', port=8001)" build-slim: docker-check docker build -t tau-rag:slim --target slim . build-full: docker-check docker build -t tau-rag:full --target full . # NOTE: quotes around "$$(pwd)/runtime" handle paths with spaces # (e.g. iCloud's "Mobile Documents" directory). run-slim: docker-check mkdir -p runtime docker run --rm -d --name tau-rag-slim -p 8000:8000 \ -v "$$(pwd)/runtime":/app/runtime tau-rag:slim run-full: docker-check mkdir -p runtime docker run --rm -d --name tau-rag-full -p 8001:8000 \ -v "$$(pwd)/runtime":/app/runtime \ -v hf-cache:/root/.cache/huggingface tau-rag:full stop: -docker stop tau-rag-slim tau-rag-full 2>/dev/null || true # If your source lives inside iCloud/OneDrive and Docker complains about # build context, this target copies tau_rag to /tmp and builds from there. # The resulting image is identical. build-from-tmp: docker-check rm -rf /tmp/tau_rag_build cp -R . /tmp/tau_rag_build cd /tmp/tau_rag_build && docker build -t tau-rag:slim --target slim . cd /tmp/tau_rag_build && docker build -t tau-rag:full --target full . @echo "✓ Built tau-rag:slim and tau-rag:full from /tmp/tau_rag_build" clean: rm -rf runtime/*.jsonl runtime/ab_report.html runtime/tau_rag_dashboard.html find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || true # ========================================================= PRODUCTION # Hardened image (non-root, healthcheck, gunicorn, tini, pinned deps) build-prod: docker-check docker build -f Dockerfile.prod -t tau-rag:prod . # Run single prod container (for testing the hardened image) run-prod: docker-check mkdir -p runtime docker run --rm -d --name tau-rag-prod -p 8000:8000 \ --env-file .env \ -v "$$(pwd)/runtime":/app/runtime \ -v hf-cache:/home/taurag/.cache/huggingface \ tau-rag:prod # Full stack (app + nginx + prometheus + grafana) prod-up: docker-check @test -f .env || (echo "❌ No .env file — cp .env.example .env and fill it in." && exit 1) docker compose -f docker-compose.prod.yml --env-file .env up -d --build prod-down: docker compose -f docker-compose.prod.yml down prod-logs: docker compose -f docker-compose.prod.yml logs -f --tail=200 prod-ps: docker compose -f docker-compose.prod.yml ps # ========================================================= KUBERNETES k8s-apply: kubectl apply -f deployment/k8s/namespace.yaml kubectl apply -f deployment/k8s/configmap.yaml @test -f deployment/k8s/secret.yaml \ || (echo "❌ deployment/k8s/secret.yaml missing. cp secret.example.yaml secret.yaml and fill it in." && exit 1) kubectl apply -f deployment/k8s/secret.yaml kubectl apply -f deployment/k8s/service.yaml kubectl apply -f deployment/k8s/deployment.yaml kubectl apply -f deployment/k8s/hpa.yaml kubectl apply -f deployment/k8s/pdb.yaml kubectl apply -f deployment/k8s/networkpolicy.yaml kubectl apply -f deployment/k8s/ingress.yaml k8s-status: kubectl -n tau-rag get pods,svc,hpa,ingress k8s-logs: kubectl -n tau-rag logs -f deploy/tau-rag --tail=200 k8s-delete: kubectl delete ns tau-rag --ignore-not-found # ========================================================= QUALITY lint: ruff check . PYTHONPATH=.. mypy . --ignore-missing-imports --exclude '^(tests|runtime)/' || true format: ruff format . security-scan: @command -v trivy >/dev/null || (echo "Install trivy: brew install trivy" && exit 1) trivy image --severity CRITICAL,HIGH --ignore-unfixed tau-rag:prod