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"]