import subprocess, sys, importlib def ensure_deps(): """Install missing dependencies at startup.""" needed = { "transformers": "transformers>=4.50.0", "bitsandbytes": "bitsandbytes>=0.45.0", "accelerate": "accelerate>=1.5.0", } missing = [pkg for mod, pkg in needed.items() if importlib.util.find_spec(mod) is None] if missing: print(f"πŸ“¦ Installiere fehlende Dependencies: {missing}") subprocess.check_call([sys.executable, "-m", "pip", "install", "--no-cache-dir"] + missing) print("βœ… Dependencies installiert!") ensure_deps() import spaces import torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import gradio as gr import time # ─── Modell ─────────────────────────────────────────────────────────────── MODEL_ID = "Qwen/Qwen3-Coder-7B-A3B-Instruct" MAX_TOKENS = 4096 DEFAULT_TEMP = 0.6 DEFAULT_SYSTEM = "You are Qwen Coder Boosted, an expert coding assistant. Generate clean, working code. Always show complete files with [FILE:filename] markers." print("πŸš€ Lade Modell...") bnb_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_use_double_quant=True, bnb_4bit_quant_type="nf4", ) tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( MODEL_ID, quantization_config=bnb_config, device_map="auto", trust_remote_code=True, torch_dtype=torch.bfloat16, attn_implementation="eager", ) print("βœ… Modell geladen!") # ─── GPU-Funktion (nur hier ist echte GPU) ────────────────────────────── @spaces.GPU(duration=240) def generate_response(messages, temperature, max_tokens): """Generate a response from the model. GPU is real inside this function.""" text = tokenizer.apply_chat_template( messages, tokenize=False, add_generation_prompt=True ) inputs = tokenizer([text], return_tensors="pt").to(model.device) with torch.no_grad(): outputs = model.generate( **inputs, max_new_tokens=max_tokens, temperature=temperature, do_sample=True, top_p=0.9, repetition_penalty=1.05, pad_token_id=tokenizer.eos_token_id, ) response = tokenizer.decode( outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True ) return response # ─── Chat-Logik ────────────────────────────────────────────────────────── def chat(message, history, system_prompt, temperature): """Handle a chat turn. Builds messages, calls GPU function, returns updated history.""" if not message.strip(): return history messages = [] if system_prompt: messages.append({"role": "system", "content": system_prompt}) for user_msg, assistant_msg in history: if user_msg: messages.append({"role": "user", "content": user_msg}) if assistant_msg: messages.append({"role": "assistant", "content": assistant_msg}) messages.append({"role": "user", "content": message}) response = generate_response(messages, temperature, MAX_TOKENS) history.append((message, response)) return history # ─── UI ────────────────────────────────────────────────────────────────── with gr.Blocks( title="Qwen Coder Boosted", ) as demo: gr.Markdown(""" # πŸš€ Qwen Coder Boosted **Qwen3-Coder-30B-A3B (4-bit) auf Zero GPU** – 48 GB shared VRAM, PRO-Quota """) with gr.Row(): with gr.Column(scale=1): system_prompt = gr.Textbox( label="βš™οΈ System Prompt", value=DEFAULT_SYSTEM, lines=3, ) temperature = gr.Slider( label="🌑️ Temperature", minimum=0.1, maximum=1.5, value=DEFAULT_TEMP, step=0.05, ) clear_btn = gr.Button("πŸ—‘οΈ Chat leeren", variant="secondary") with gr.Column(scale=3): chatbot = gr.Chatbot( label="πŸ’¬ Chat", height=550, ) with gr.Row(): msg = gr.Textbox( label="Deine Nachricht", placeholder="Schreib einen Prompt... z.B. 'Baue eine To-Do-App mit HTML/CSS/JS'", scale=8, container=True, ) submit = gr.Button("πŸ“€ Senden", variant="primary", scale=1) gr.Markdown(""" --- ### πŸ’‘ Info - **Modell:** Qwen3-Coder-30B-A3B (4-bit, ~15 GB VRAM) - **Zero GPU:** 48 GB shared, PRO = 40 Min/Tag inklusive - **Max Tokens:** 32K (hardcodiert) - **Temperature:** 0.6 (Standard fΓΌr Coding) """) submit.click( fn=chat, inputs=[msg, chatbot, system_prompt, temperature], outputs=[chatbot], ).then( fn=lambda: "", outputs=[msg], ) msg.submit( fn=chat, inputs=[msg, chatbot, system_prompt, temperature], outputs=[chatbot], ).then( fn=lambda: "", outputs=[msg], ) clear_btn.click(fn=lambda: None, outputs=[chatbot]) if __name__ == "__main__": demo.launch(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="indigo"))