strfry commited on
Commit
4fbadd3
·
verified ·
1 Parent(s): a14a1a8

Fix: restore correct requirements.txt

Browse files
Files changed (1) hide show
  1. requirements.txt +6 -134
requirements.txt CHANGED
@@ -1,134 +1,6 @@
1
- """Gradio demo for the New Prussian translator (Apertus-8B-int8 + LoRA).
2
-
3
- Loads the pre-quantized int8 base model `strfry/Apertus-8B-Instruct-2509-int8`
4
- and applies the LoRA adapter `strfry/apertus-8b-prussian-youtube` — all at
5
- module level on CPU. ZeroGPU transfers everything to VRAM automatically when
6
- a request enters @spaces.GPU. No lazy loading, no safetensors CUDA issues.
7
- """
8
-
9
- import json
10
- import torch
11
- import gradio as gr
12
- import safetensors.torch
13
- from huggingface_hub import hf_hub_download
14
- from transformers import AutoModelForCausalLM, AutoTokenizer
15
- from peft import PeftModel, LoraConfig
16
-
17
- # ZeroGPU decorator if available; no-op fallback so the app also runs locally
18
- try:
19
- import spaces
20
-
21
- GPU = spaces.GPU
22
- except ImportError: # local / non-ZeroGPU
23
-
24
- def GPU(func=None, **_kwargs):
25
- if func is None:
26
- return lambda f: f
27
- return func
28
-
29
-
30
- BASE_MODEL = "strfry/Apertus-8B-Instruct-2509-int8"
31
- ADAPTER = "strfry/apertus-8b-prussian-youtube"
32
-
33
- SYSTEM_PROMPT = "Translate to reconstructed neo-prussian:"
34
- MAX_NEW_TOKENS = 100
35
-
36
- # ── All initialisation happens at module level (ZeroGPU best practice) ─────
37
- # Tokenizer from the adapter repo (carries the chatml template).
38
- _tokenizer = AutoTokenizer.from_pretrained(ADAPTER, trust_remote_code=True)
39
-
40
- # Pre-quantized int8 base model — quantization_config is baked into config.json
41
- # so no BitsAndBytesConfig is needed. device_map="auto" works with ZeroGPU's
42
- # CUDA emulation at import time, then ZeroGPU swaps in real CUDA at request time.
43
- _base = AutoModelForCausalLM.from_pretrained(
44
- BASE_MODEL,
45
- device_map="auto",
46
- trust_remote_code=True,
47
- )
48
-
49
- # Attach the LoRA adapter using EXPLICIT CPU loading to avoid the safetensors
50
- # CUDA path that fails in ZeroGPU's emulation mode (RuntimeError: No CUDA GPUs
51
- # are available). PeftModel.from_pretrained() triggers __torch_dispatch__ hooks;
52
- # loading weights manually on CPU bypasses that.
53
- _config_path = hf_hub_download(ADAPTER, "adapter_config.json")
54
- with open(_config_path) as f:
55
- _peft_config = LoraConfig(**json.load(f))
56
-
57
- _model = PeftModel(_base, _peft_config)
58
-
59
- _weights_path = hf_hub_download(ADAPTER, "adapter_model.safetensors")
60
- _adapter_weights = safetensors.torch.load_file(_weights_path, device="cpu")
61
- _model.load_state_dict(_adapter_weights, strict=False)
62
- _model.eval()
63
-
64
-
65
- @GPU(duration=120)
66
- def translate(text: str) -> str:
67
- """Tokenize, generate, decode — the GPU-heavy work lives here."""
68
- if not text.strip():
69
- return ""
70
-
71
- messages = [
72
- {"role": "system", "content": SYSTEM_PROMPT},
73
- {"role": "user", "content": text.strip()},
74
- ]
75
- inputs = (
76
- _tokenizer.apply_chat_template(
77
- messages,
78
- add_generation_prompt=True,
79
- return_tensors="pt",
80
- return_dict=True,
81
- )
82
- .to(_base.device)
83
- )
84
-
85
- # <|im_end|> is NOT a single special token in the base tokenizer — the
86
- # model was trained to output it as subword pieces. eos_token_id cannot
87
- # help here (it points to <|assistant_end|>, which the adapter never
88
- # generates). We clean up after decoding instead.
89
- with torch.no_grad():
90
- out = _model.generate(
91
- **inputs,
92
- max_new_tokens=MAX_NEW_TOKENS,
93
- do_sample=False,
94
- repetition_penalty=1.2,
95
- pad_token_id=_tokenizer.eos_token_id,
96
- )
97
- new_tokens = out[0][inputs["input_ids"].shape[1] :]
98
- result = _tokenizer.decode(new_tokens, skip_special_tokens=False).strip()
99
- result = result.replace("<|im_end|>", "").strip()
100
- cutoff = result.find("<|im_start|>")
101
- if cutoff != -1:
102
- result = result[:cutoff].strip()
103
- return result
104
-
105
-
106
- with gr.Blocks(title="New Prussian Translator") as demo:
107
- gr.Markdown(
108
- "# New Prussian Translator\n"
109
- "Apertus-8B + LoRA. Translates **into** reconstructed neo-Prussian "
110
- "from German, English, Lithuanian, Latvian, … Model is pre-loaded — "
111
- "queries complete in a few seconds."
112
- )
113
- gr.Markdown(f"**Fixed system prompt:** `{SYSTEM_PROMPT}`")
114
- with gr.Row():
115
- with gr.Column():
116
- text = gr.Textbox(lines=4, label="Source text")
117
- btn = gr.Button("Translate", variant="primary")
118
- with gr.Column():
119
- output = gr.Textbox(lines=4, label="New Prussian")
120
-
121
- gr.Examples(
122
- examples=[
123
- ["Ich gehe in den Wald"],
124
- ["All is very white."],
125
- ["Wie heißt du?"],
126
- ],
127
- inputs=[text],
128
- )
129
-
130
- btn.click(translate, text, output)
131
- text.submit(translate, text, output)
132
-
133
- if __name__ == "__main__":
134
- demo.launch()
 
1
+ torch
2
+ transformers
3
+ accelerate
4
+ peft
5
+ bitsandbytes
6
+ spaces