uwe311 commited on
Commit
0670603
Β·
1 Parent(s): 0089e1b

Zero GPU: Qwen3-Coder-30B-A3B (4-bit) mit @spaces.GPU

Browse files
Files changed (2) hide show
  1. app.py +156 -4
  2. requirements.txt +6 -0
app.py CHANGED
@@ -1,7 +1,159 @@
 
 
 
1
  import gradio as gr
 
2
 
3
- def greet(name):
4
- return "Hello " + name + "!!"
 
 
 
5
 
6
- demo = gr.Interface(fn=greet, inputs="text", outputs="text")
7
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import spaces
2
+ import torch
3
+ from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
4
  import gradio as gr
5
+ import time
6
 
7
+ # ─── Modell ───────────────────────────────────────────────────────────────
8
+ MODEL_ID = "Qwen/Qwen3-Coder-30B-A3B-Instruct"
9
+ MAX_TOKENS = 32768
10
+ DEFAULT_TEMP = 0.6
11
+ DEFAULT_SYSTEM = "You are Qwen Coder Boosted, an expert coding assistant. Generate clean, working code. Always show complete files with [FILE:filename] markers."
12
 
13
+ print("πŸš€ Lade Modell...")
14
+ bnb_config = BitsAndBytesConfig(
15
+ load_in_4bit=True,
16
+ bnb_4bit_compute_dtype=torch.bfloat16,
17
+ bnb_4bit_use_double_quant=True,
18
+ bnb_4bit_quant_type="nf4",
19
+ )
20
+
21
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
22
+ model = AutoModelForCausalLM.from_pretrained(
23
+ MODEL_ID,
24
+ quantization_config=bnb_config,
25
+ device_map="auto",
26
+ trust_remote_code=True,
27
+ torch_dtype=torch.bfloat16,
28
+ attn_implementation="flash_attention_2",
29
+ )
30
+ print("βœ… Modell geladen!")
31
+
32
+
33
+ # ─── GPU-Funktion (nur hier ist echte GPU) ──────────────────────────────
34
+ @spaces.GPU(duration=120)
35
+ def generate_response(messages, temperature, max_tokens):
36
+ """Generate a response from the model. GPU is real inside this function."""
37
+ text = tokenizer.apply_chat_template(
38
+ messages, tokenize=False, add_generation_prompt=True
39
+ )
40
+ inputs = tokenizer([text], return_tensors="pt").to(model.device)
41
+
42
+ with torch.no_grad():
43
+ outputs = model.generate(
44
+ **inputs,
45
+ max_new_tokens=max_tokens,
46
+ temperature=temperature,
47
+ do_sample=True,
48
+ top_p=0.9,
49
+ repetition_penalty=1.05,
50
+ pad_token_id=tokenizer.eos_token_id,
51
+ )
52
+
53
+ response = tokenizer.decode(
54
+ outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True
55
+ )
56
+ return response
57
+
58
+
59
+ # ─── Chat-Logik ──────────────────────────────────────────────────────────
60
+ def chat(message, history, system_prompt, temperature):
61
+ """Handle a chat turn. Builds messages, calls GPU function, returns updated history."""
62
+ if not message.strip():
63
+ return history
64
+
65
+ # Build messages array from history
66
+ messages = []
67
+ if system_prompt:
68
+ messages.append({"role": "system", "content": system_prompt})
69
+ for user_msg, assistant_msg in history:
70
+ if user_msg:
71
+ messages.append({"role": "user", "content": user_msg})
72
+ if assistant_msg:
73
+ messages.append({"role": "assistant", "content": assistant_msg})
74
+ messages.append({"role": "user", "content": message})
75
+
76
+ # Generate (this triggers @spaces.GPU)
77
+ response = generate_response(messages, temperature, MAX_TOKENS)
78
+
79
+ # Update history
80
+ history.append((message, response))
81
+ return history
82
+
83
+
84
+ # ─── UI ──────────────────────────────────────────────────────────────────
85
+ with gr.Blocks(
86
+ theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"),
87
+ title="Qwen Coder Boosted",
88
+ ) as demo:
89
+ gr.Markdown("""
90
+ # πŸš€ Qwen Coder Boosted
91
+ **Qwen3-Coder-30B-A3B (4-bit) auf Zero GPU** – 48 GB shared VRAM, PRO-Quota
92
+ """)
93
+
94
+ with gr.Row():
95
+ with gr.Column(scale=1):
96
+ system_prompt = gr.Textbox(
97
+ label="βš™οΈ System Prompt",
98
+ value=DEFAULT_SYSTEM,
99
+ lines=3,
100
+ )
101
+ temperature = gr.Slider(
102
+ label="🌑️ Temperature",
103
+ minimum=0.1,
104
+ maximum=1.5,
105
+ value=DEFAULT_TEMP,
106
+ step=0.05,
107
+ )
108
+ clear_btn = gr.Button("πŸ—‘οΈ Chat leeren", variant="secondary")
109
+
110
+ with gr.Column(scale=3):
111
+ chatbot = gr.Chatbot(
112
+ label="πŸ’¬ Chat",
113
+ height=550,
114
+ bubble_full_width=False,
115
+ show_copy_button=True,
116
+ )
117
+
118
+ with gr.Row():
119
+ msg = gr.Textbox(
120
+ label="Deine Nachricht",
121
+ placeholder="Schreib einen Prompt... z.B. 'Baue eine To-Do-App mit HTML/CSS/JS'",
122
+ scale=8,
123
+ container=True,
124
+ )
125
+ submit = gr.Button("πŸ“€ Senden", variant="primary", scale=1)
126
+
127
+ gr.Markdown("""
128
+ ---
129
+ ### πŸ’‘ Info
130
+ - **Modell:** Qwen3-Coder-30B-A3B (4-bit, ~15 GB VRAM)
131
+ - **Zero GPU:** 48 GB shared, PRO = 40 Min/Tag inklusive
132
+ - **Max Tokens:** 32K (hardcodiert)
133
+ - **Temperature:** 0.6 (Standard fΓΌr Coding)
134
+ """)
135
+
136
+ # Events
137
+ submit.click(
138
+ fn=chat,
139
+ inputs=[msg, chatbot, system_prompt, temperature],
140
+ outputs=[chatbot],
141
+ ).then(
142
+ fn=lambda: "",
143
+ outputs=[msg],
144
+ )
145
+
146
+ msg.submit(
147
+ fn=chat,
148
+ inputs=[msg, chatbot, system_prompt, temperature],
149
+ outputs=[chatbot],
150
+ ).then(
151
+ fn=lambda: "",
152
+ outputs=[msg],
153
+ )
154
+
155
+ clear_btn.click(fn=lambda: None, outputs=[chatbot])
156
+
157
+
158
+ if __name__ == "__main__":
159
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ spaces>=1.0.0
2
+ torch>=2.8.0
3
+ transformers>=4.50.0
4
+ bitsandbytes>=0.45.0
5
+ accelerate>=1.5.0
6
+ gradio>=5.0.0