File size: 2,849 Bytes
39cfcd1 | 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 | # ZuZu Grammar — self-hosted LanguageTool
ZuZu Grammar uses **LanguageTool** for full sentence grammar, spelling, and punctuation.
If LanguageTool is offline, the API falls back to basic local rules.
## Hugging Face Spaces (recommended)
The Docker image **embeds LanguageTool** and starts it with the app (`scripts/start.sh`).
1. Redeploy the Space (rebuild the image).
2. First boot can take **1–3 minutes** while Java + LT warm up.
3. Check `GET /health` → `"languagetool": { "reachable": true }`.
4. Space secrets (optional overrides):
```env
LANGUAGE_TOOL_EMBEDDED=true
LANGUAGE_TOOL_URL=http://127.0.0.1:8010
LANGUAGE_TOOL_LANGUAGE=en-US
LANGUAGE_TOOL_ENABLED=true
LANGUAGE_TOOL_TIMEOUT=90
LANGUAGE_TOOL_CHUNK_CHARS=1800
GRAMMAR_MAX_CHARS=12000
LANGUAGETOOL_JAVA_OPTS=-Xms256m -Xmx1024m
```
Needs about **1–2 GB RAM**. If the Space OOMs, raise Space hardware or lower `-Xmx` (Java 21 is used in the image).
Long drafts are **split into ~1800-character chunks** so one long paragraph does not OOM LanguageTool. Pastes over `GRAMMAR_MAX_CHARS` (default 12,000) return a clear 413 instead of a raw 500.
**Do not** set `LANGUAGE_TOOL_URL` to a host that isn’t running LT (that causes `Connection refused` and the “offline” fallback message).
## Local: LanguageTool only + `python app.py`
```bash
docker compose up languagetool -d
```
Wait until healthy, then in `.env`:
```env
LANGUAGE_TOOL_URL=http://127.0.0.1:8010
LANGUAGE_TOOL_LANGUAGE=en-US
LANGUAGE_TOOL_ENABLED=true
```
`LANGUAGE_TOOL_LANGUAGE` is the server default (en-US). The Grammar UI can override per check (`en-GB`, etc.).
```bash
curl -s http://127.0.0.1:8010/v2/languages | head
python app.py
```
## Local: full Compose (app + LT sidecar)
```bash
docker compose up --build
```
App: http://127.0.0.1:7860
LanguageTool: http://127.0.0.1:8010
Compose sets `LANGUAGE_TOOL_EMBEDDED=false` and `LANGUAGE_TOOL_URL=http://languagetool:8010`.
## Health
```json
"languagetool": { "configured": true, "reachable": true, "default_language": "en-US" }
```
When reachable, grammar responses use `"engine": "languagetool"`.
## Troubleshooting `Connection refused`
| Cause | Fix |
|--------|-----|
| LT container not running | `docker compose up languagetool -d` |
| App URL wrong | Local app → `http://127.0.0.1:8010`; Compose app → `http://languagetool:8010`; Space embedded → `http://127.0.0.1:8010` |
| Space still on old image | Rebuild/redeploy so embedded LT + `start.sh` are included |
| LT still starting | Wait 1–2 min; watch logs for `LanguageTool ready` |
| Long text → HTTP 500 | Redeploy latest build (sentence chunking + higher heap). Over `GRAMMAR_MAX_CHARS` now returns a clear 413. |
## Resources
LanguageTool needs roughly **1–2 GB RAM**.
|