Cnass commited on
Commit
60367fd
Β·
verified Β·
1 Parent(s): 0f5268a

Upload 2 files

Browse files
Files changed (2) hide show
  1. README.md +85 -1
  2. requirements.txt +2 -0
README.md CHANGED
@@ -21,6 +21,9 @@ localisation actually needs β€” a project glossary, a pinned register, and
21
  passthrough for control-code-only lines. See
22
  [Keeping 50k strings consistent](#keeping-50k-strings-consistent).
23
 
 
 
 
24
  ## How it works
25
 
26
  - **Inference engine**: `llama-server`, taken as-is from the official
@@ -40,7 +43,85 @@ passthrough for control-code-only lines. See
40
  - Chat formatting uses the GGUF's embedded Jinja chat template
41
  (`llama-server --jinja`), matching the model card's documented usage.
42
 
43
- ## Endpoints
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
 
45
  ### `GET /health`
46
  Backend status check.
@@ -130,6 +211,9 @@ Set the `API_KEY` env var on the Space to require an `X-API-Key` header on
130
  | `CTX_SIZE` | `32768` | total context, split across `PARALLEL_SLOTS` slots (2048 each). Costs VRAM β€” see [VRAM budget](#vram-budget) |
131
  | `MAX_TOKENS` | `512` | max output tokens per translation |
132
  | `MAX_BATCH_SIZE` | `200` | max items accepted per `/translate/batch` call |
 
 
 
133
  | `PROMPT_FORMAT` | inferred | `hy-mt2` or `rosetta` β€” see [Switching model family](#switching-model-family). Inferred from `MODEL_REPO`, so you rarely set it by hand |
134
  | `TEMPERATURE`/`TOP_P`/`TOP_K`/`REPEAT_PENALTY` | per family | `0.7`/`0.6`/`20`/`1.05` for Hy-MT2 (its model card's values), `0.7`/`0.95`/`64`/`1.0` for Rosetta (Gemma 3 defaults) |
135
  | `API_KEY` | *(empty)* | optional shared secret for `X-API-Key` |
 
21
  passthrough for control-code-only lines. See
22
  [Keeping 50k strings consistent](#keeping-50k-strings-consistent).
23
 
24
+ Point it at a zipped RPG Maker MV/MZ `data` folder and it translates the game
25
+ end to end: see [Translating an RPG Maker game](#translating-an-rpg-maker-game).
26
+
27
  ## How it works
28
 
29
  - **Inference engine**: `llama-server`, taken as-is from the official
 
43
  - Chat formatting uses the GGUF's embedded Jinja chat template
44
  (`llama-server --jinja`), matching the model card's documented usage.
45
 
46
+ ## Translating an RPG Maker game
47
+
48
+ Upload the game's data folder as a zip and the whole extract β†’ translate β†’
49
+ repack cycle runs server-side. Open `/rpgm.html` on the Space for the UI, or
50
+ drive it over the API:
51
+
52
+ ```bash
53
+ BASE=https://your-space.hf.space
54
+ ID=$(curl -sF file=@data.zip $BASE/project/upload | jq -r .id)
55
+ curl -s -X POST $BASE/project/$ID/start -H 'Content-Type: application/json' \
56
+ -d '{"target_lang":"tr"}'
57
+ curl -s $BASE/project/$ID/status | jq '.percent, .files'
58
+ curl -so translated.zip $BASE/project/$ID/download
59
+ ```
60
+
61
+ Zip the `data` folder (MZ) or `www/data` (MV) β€” not the whole game. Both
62
+ layouts are detected automatically.
63
+
64
+ ### What gets translated
65
+
66
+ Only dialogue, and deliberately so. RPG Maker keeps executable script, plugin
67
+ bindings, asset filenames and engine identifiers in the same arrays as the
68
+ lines an actor speaks, and translating one of those breaks the game rather
69
+ than mistranslating it.
70
+
71
+ | event code | content | translated |
72
+ |---|---|---|
73
+ | 401 / 405 | Show Text / Scrolling Text | **yes** |
74
+ | 102 / 402 | Show Choices / When[choice] | **yes** |
75
+ | 101 | message header, incl. the MZ speaker name | no |
76
+ | 355 / 655 | Script (executable JS) | no |
77
+ | 356 / 357 | Plugin Command | no |
78
+ | 320 / 324 / 325 | Change Name / Nickname / Profile | no |
79
+
80
+ Database files (`Actors.json`, `Items.json`, …), `System.json` terms and
81
+ `plugins.js` are left untouched.
82
+
83
+ Three details make the output safe to ship:
84
+
85
+ - **Message boxes stay whole.** A run of consecutive 401 commands is one box
86
+ split across lines, not separate sentences, so the run is merged and
87
+ translated as a single piece β€” then re-wrapped into exactly the original
88
+ number of lines. Adding or removing entries in an event list would shift
89
+ every index after it and break conditional branches, so the line count is
90
+ an invariant.
91
+ - **Repeats are translated once.** Units are keyed by source text across the
92
+ whole project: in a real game an 800-slot map set collapses to ~150 unique
93
+ strings, and a "Yes" that appears 300 times costs one generation. It also
94
+ keeps a 102 choice and its 402 mirror automatically identical.
95
+ - **A mangled control code is never written.** After each translation the
96
+ multiset of control codes (`\C[2]`, `\N[1]`, `\V[3]`, `\I[5]`,
97
+ `<WordWrap>`, …) is compared against the source. On a mismatch the source
98
+ line is kept and the string is listed under *review* in the UI β€” a leftover
99
+ English line is cosmetic, a broken `\C[2` is a rendering bug in the
100
+ shipped game.
101
+
102
+ Untranslated strings keep their source text, so the download is a playable
103
+ game at any point, not just when the run finishes.
104
+
105
+ ### Project endpoints
106
+
107
+ | method | path | purpose |
108
+ |---|---|---|
109
+ | `POST` | `/project/upload` | multipart zip; unpacks, detects MV/MZ, indexes dialogue |
110
+ | `POST` | `/project/{id}/start` | begin (or resume) translating; body `{"target_lang":"tr"}` |
111
+ | `GET` | `/project/{id}/status` | overall %, per-file %, review list |
112
+ | `POST` | `/project/{id}/cancel` | stop after in-flight strings finish |
113
+ | `GET` | `/project/{id}/download` | rebuilt zip, same folder layout |
114
+ | `DELETE` | `/project/{id}` | remove immediately |
115
+ | `GET` | `/project` | list projects and which one holds the GPU |
116
+
117
+ One run at a time β€” there is a single GPU, so a second concurrent project
118
+ would only make both finish later. Progress is written to disk continuously
119
+ and a run interrupted by the Space sleeping is **resumed on startup**, which
120
+ is why `PROJECT_DIR` defaults to the persistent volume (`/data/projects`)
121
+ when one is mounted. Uploads are deleted after `PROJECT_RETENTION_HOURS`
122
+ (default 24).
123
+
124
+ ## Translation endpoints
125
 
126
  ### `GET /health`
127
  Backend status check.
 
211
  | `CTX_SIZE` | `32768` | total context, split across `PARALLEL_SLOTS` slots (2048 each). Costs VRAM β€” see [VRAM budget](#vram-budget) |
212
  | `MAX_TOKENS` | `512` | max output tokens per translation |
213
  | `MAX_BATCH_SIZE` | `200` | max items accepted per `/translate/batch` call |
214
+ | `PROJECT_DIR` | `/data/projects` if mounted, else `/app/projects` | where uploaded RPG Maker projects and their progress live |
215
+ | `PROJECT_RETENTION_HOURS` | `24` | uploaded projects are deleted this long after their last update |
216
+ | `MAX_UPLOAD_MB` | `200` | rejects uploads bigger than this |
217
  | `PROMPT_FORMAT` | inferred | `hy-mt2` or `rosetta` β€” see [Switching model family](#switching-model-family). Inferred from `MODEL_REPO`, so you rarely set it by hand |
218
  | `TEMPERATURE`/`TOP_P`/`TOP_K`/`REPEAT_PENALTY` | per family | `0.7`/`0.6`/`20`/`1.05` for Hy-MT2 (its model card's values), `0.7`/`0.95`/`64`/`1.0` for Rosetta (Gemma 3 defaults) |
219
  | `API_KEY` | *(empty)* | optional shared secret for `X-API-Key` |
requirements.txt CHANGED
@@ -3,3 +3,5 @@ uvicorn[standard]==0.34.0
3
  httpx==0.28.1
4
  pydantic==2.10.5
5
  huggingface_hub==0.27.1
 
 
 
3
  httpx==0.28.1
4
  pydantic==2.10.5
5
  huggingface_hub==0.27.1
6
+ # Required by FastAPI's UploadFile: without it /project/upload raises at import.
7
+ python-multipart==0.0.20