File size: 3,625 Bytes
24a79a8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | # Existing React interface
FROM node:22-alpine AS frontend
WORKDIR /web
ENV NODE_TLS_REJECT_UNAUTHORIZED=0
COPY frontend/package.json frontend/package-lock.json ./
RUN npm ci
COPY frontend/ ./
RUN npm run build
# Backend API + embedded LanguageTool for HF Spaces / single-container
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \
PIP_NO_CACHE_DIR=1 \
HOST=0.0.0.0 \
PORT=7860 \
APP_TITLE="ZuZu Writer" \
WN_DATA_DIR=/opt/wn_data \
ENGINE_PARAPHRASE=true \
ENGINE_PARAPHRASE_PRIMARY=true \
ENGINE_PARAPHRASE_MODEL=Vamsi/T5_Paraphrase_Paws \
ENGINE_PARAPHRASE_MIN_SIM=0.72 \
ENGINE_PARAPHRASE_NUM_RETURN=6 \
ENGINE_PARAPHRASE_MAX_NEW_TOKENS=72 \
ENGINE_PARAPHRASE_MAX_SURFACE=0.70 \
ENGINE_PARAPHRASE_MIN_DIVERGENCE=0.30 \
ENGINE_FORCE_REWRITE=false \
ENGINE_USE_MINILM_SAFETY=true \
ENGINE_CLASSICAL_AGGRESSIVE=true \
ENGINE_STRUCTURAL_VARIATION=true \
ENGINE_LEXICAL_REFINEMENT=true \
ENGINE_PHRASE_REWRITE=true \
ENGINE_PHRASE_USE_T5=false \
ENGINE_PRESERVE_LENGTH=true \
ENGINE_SPLIT_LONG=true \
HF_HOME=/opt/hf_cache \
TRANSFORMERS_CACHE=/opt/hf_cache \
SENTENCE_TRANSFORMERS_HOME=/opt/hf_cache \
LANGUAGETOOL_HOME=/opt/languagetool \
LANGUAGETOOL_PORT=8010 \
LANGUAGE_TOOL_URL=http://127.0.0.1:8010 \
LANGUAGE_TOOL_ENABLED=true \
LANGUAGE_TOOL_EMBEDDED=true \
LANGUAGE_TOOL_LANGUAGE=en-US \
LANGUAGE_TOOL_TIMEOUT=90 \
LANGUAGE_TOOL_CHUNK_CHARS=1800 \
GRAMMAR_MAX_CHARS=12000 \
LANGUAGETOOL_JAVA_OPTS="-Xms256m -Xmx1024m"
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
curl \
ca-certificates \
unzip \
openjdk-21-jre-headless \
&& rm -rf /var/lib/apt/lists/*
# LanguageTool stable server (self-hosted grammar)
RUN curl -fsSL -o /tmp/lt.zip https://languagetool.org/download/LanguageTool-stable.zip \
&& unzip -q /tmp/lt.zip -d /opt \
&& LT_DIR="$(find /opt -maxdepth 1 -type d -name 'LanguageTool-*' | head -n 1)" \
&& mv "$LT_DIR" /opt/languagetool \
&& rm -f /tmp/lt.zip \
&& test -f /opt/languagetool/languagetool-server.jar
COPY requirements.txt .
# spaCy model wheel is listed in requirements.txt.
# CPU torch + transformers power the local T5 paraphraser and MiniLM ranker.
RUN pip install --upgrade pip \
&& pip install --index-url https://download.pytorch.org/whl/cpu torch \
&& pip install -r requirements.txt
# Offline lexical resource used only when ENGINE_LEXICAL_REFINEMENT=true.
RUN curl -fsSL -o /tmp/oewn.xml.gz \
https://github.com/globalwordnet/english-wordnet/releases/download/2025-edition/english-wordnet-2025.xml.gz \
&& python -c "import wn; wn.add('/tmp/oewn.xml.gz')" \
&& rm -f /tmp/oewn.xml.gz
COPY app ./app
COPY app.py .
COPY README.md .
COPY scripts/start.sh /app/scripts/start.sh
RUN sed -i 's/\r$//' /app/scripts/start.sh && chmod +x /app/scripts/start.sh
COPY --from=frontend /web/dist ./frontend/dist
# Prefetch paraphrase + MiniLM so Space cold-start does not hit the Hub.
RUN python - <<'PY'
from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
name = "Vamsi/T5_Paraphrase_Paws"
AutoTokenizer.from_pretrained(name)
AutoModelForSeq2SeqLM.from_pretrained(name)
from app.pipeline.minilm import warm_minilm
ok = warm_minilm()
print("prefetch ok", name, "minilm", ok)
PY
EXPOSE 7860
# LT cold-start can take 1–2 minutes
HEALTHCHECK --interval=30s --timeout=5s --start-period=180s --retries=5 \
CMD curl -fsS http://127.0.0.1:7860/health || exit 1
CMD ["/app/scripts/start.sh"]
|