Update app.py
Browse files
app.py
CHANGED
@@ -14,16 +14,14 @@ tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True, toke
|
|
14 |
|
15 |
if tokenizer.pad_token is None:
|
16 |
print("pad_token nicht gesetzt, verwende eos_token als pad_token.")
|
17 |
-
tokenizer.pad_token = tokenizer.eos_token
|
18 |
|
19 |
print(f"Lade Modell: {MODEL_ID} auf CPU. Dies kann einige Zeit dauern...")
|
20 |
-
# Versuche, das Modell in bfloat16 zu laden, um RAM zu sparen, wie auf dem Screenshot angedeutet.
|
21 |
-
# Wenn die CPU bfloat16 nicht gut unterstützt, könnte float32 stabiler, aber speicherintensiver sein.
|
22 |
try:
|
23 |
model = AutoModelForCausalLM.from_pretrained(
|
24 |
MODEL_ID,
|
25 |
-
torch_dtype=torch.bfloat16,
|
26 |
-
device_map="cpu",
|
27 |
trust_remote_code=True,
|
28 |
token=HF_TOKEN
|
29 |
)
|
@@ -31,70 +29,57 @@ except Exception as e:
|
|
31 |
print(f"Fehler beim Laden mit bfloat16 ({e}), versuche float32...")
|
32 |
model = AutoModelForCausalLM.from_pretrained(
|
33 |
MODEL_ID,
|
34 |
-
torch_dtype=torch.float32,
|
35 |
device_map="cpu",
|
36 |
trust_remote_code=True,
|
37 |
token=HF_TOKEN
|
38 |
)
|
39 |
|
40 |
-
model.eval()
|
41 |
print("Modell und Tokenizer erfolgreich geladen.")
|
42 |
|
43 |
# --- Vorhersagefunktion für das ChatInterface ---
|
44 |
def predict(message, history):
|
45 |
-
# Formatieren der History und der aktuellen Nachricht für das Modell
|
46 |
-
# Qwen3 verwendet ein spezifisches Chat-Template
|
47 |
messages_for_template = []
|
48 |
-
for user_msg, ai_msg in history:
|
49 |
messages_for_template.append({"role": "user", "content": user_msg})
|
50 |
messages_for_template.append({"role": "assistant", "content": ai_msg})
|
51 |
messages_for_template.append({"role": "user", "content": message})
|
52 |
|
53 |
try:
|
54 |
-
# Anwenden des Chat-Templates
|
55 |
prompt = tokenizer.apply_chat_template(
|
56 |
messages_for_template,
|
57 |
tokenize=False,
|
58 |
-
add_generation_prompt=True
|
59 |
)
|
60 |
except Exception as e:
|
61 |
print(f"Fehler beim Anwenden des Chat-Templates: {e}")
|
62 |
-
# Fallback, falls apply_chat_template Probleme macht (sollte bei Qwen3 aber gehen)
|
63 |
prompt_parts = []
|
64 |
for turn in messages_for_template:
|
65 |
prompt_parts.append(f"<|im_start|>{turn['role']}\n{turn['content']}<|im_end|>")
|
66 |
prompt = "\n".join(prompt_parts) + "\n<|im_start|>assistant\n"
|
67 |
|
68 |
-
|
69 |
inputs = tokenizer(prompt, return_tensors="pt", padding=True, truncation=True).to("cpu")
|
70 |
|
71 |
-
# Generierungsparameter (kannst du anpassen)
|
72 |
generation_kwargs = {
|
73 |
"max_new_tokens": 512,
|
74 |
"temperature": 0.7,
|
75 |
"top_p": 0.9,
|
76 |
"top_k": 50,
|
77 |
"do_sample": True,
|
78 |
-
"pad_token_id": tokenizer.eos_token_id,
|
79 |
}
|
80 |
|
81 |
print("Generiere Antwort...")
|
82 |
-
# Deaktiviere Gradientenberechnung für schnellere Inferenz und weniger Speicher
|
83 |
with torch.no_grad():
|
84 |
outputs = model.generate(**inputs, **generation_kwargs)
|
85 |
|
86 |
-
# Dekodiere nur die neu generierten Tokens
|
87 |
response_ids = outputs[0][inputs.input_ids.shape[-1]:]
|
88 |
response = tokenizer.decode(response_ids, skip_special_tokens=True)
|
89 |
-
|
90 |
print(f"Antwort: {response}")
|
91 |
-
|
92 |
-
# Für ChatInterface muss die Antwort als Stream (yield) oder als ganzer String zurückgegeben werden.
|
93 |
-
# Für CPU ist ein Stream nicht sinnvoll, da die Generierung ohnehin blockiert.
|
94 |
return response
|
95 |
|
96 |
# --- Gradio UI ---
|
97 |
-
# Verwende gr.Blocks für mehr Kontrolle über das Layout und Theme
|
98 |
with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Qwen3 8B (CPU)") as demo:
|
99 |
gr.Markdown(
|
100 |
"""
|
@@ -104,37 +89,38 @@ with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Qwen3 8B (CPU)") as demo:
|
|
104 |
Bitte habe Geduld.
|
105 |
"""
|
106 |
)
|
107 |
-
# ChatInterface ist ideal für eine ChatGPT-ähnliche UI
|
108 |
chatbot_interface = gr.ChatInterface(
|
109 |
fn=predict,
|
110 |
chatbot=gr.Chatbot(
|
111 |
height=600,
|
112 |
label="Chat",
|
113 |
-
show_label=False,
|
114 |
-
bubble_full_width=False #
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
115 |
),
|
116 |
textbox=gr.Textbox(
|
117 |
placeholder="Stelle mir eine Frage...",
|
118 |
-
container=False,
|
119 |
-
scale=7
|
120 |
),
|
121 |
-
# title="DeepSeek Qwen3 8B Chat (CPU)", # Titel schon im Markdown oben
|
122 |
-
# description="...", # Beschreibung schon im Markdown oben
|
123 |
examples=[
|
124 |
["Hallo, wer bist du?"],
|
125 |
["Was ist die Hauptstadt von Frankreich?"],
|
126 |
["Schreibe ein kurzes Gedicht über KI."]
|
127 |
],
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
#
|
132 |
)
|
133 |
gr.Markdown("Modell von [deepseek-ai](https://huggingface.co/deepseek-ai) auf Hugging Face.")
|
134 |
|
135 |
-
|
136 |
-
# --- Starte die App ---
|
137 |
if __name__ == "__main__":
|
138 |
-
# Share=True ist nicht nötig, wenn es auf HF Spaces läuft
|
139 |
-
# In_browser=True öffnet es lokal im Browser, wenn du es lokal testest
|
140 |
demo.launch()
|
|
|
14 |
|
15 |
if tokenizer.pad_token is None:
|
16 |
print("pad_token nicht gesetzt, verwende eos_token als pad_token.")
|
17 |
+
tokenizer.pad_token = tokenizer.eos_token
|
18 |
|
19 |
print(f"Lade Modell: {MODEL_ID} auf CPU. Dies kann einige Zeit dauern...")
|
|
|
|
|
20 |
try:
|
21 |
model = AutoModelForCausalLM.from_pretrained(
|
22 |
MODEL_ID,
|
23 |
+
torch_dtype=torch.bfloat16,
|
24 |
+
device_map="cpu",
|
25 |
trust_remote_code=True,
|
26 |
token=HF_TOKEN
|
27 |
)
|
|
|
29 |
print(f"Fehler beim Laden mit bfloat16 ({e}), versuche float32...")
|
30 |
model = AutoModelForCausalLM.from_pretrained(
|
31 |
MODEL_ID,
|
32 |
+
torch_dtype=torch.float32,
|
33 |
device_map="cpu",
|
34 |
trust_remote_code=True,
|
35 |
token=HF_TOKEN
|
36 |
)
|
37 |
|
38 |
+
model.eval()
|
39 |
print("Modell und Tokenizer erfolgreich geladen.")
|
40 |
|
41 |
# --- Vorhersagefunktion für das ChatInterface ---
|
42 |
def predict(message, history):
|
|
|
|
|
43 |
messages_for_template = []
|
44 |
+
for user_msg, ai_msg in history: # history ist jetzt eine Liste von Listen/Tupeln
|
45 |
messages_for_template.append({"role": "user", "content": user_msg})
|
46 |
messages_for_template.append({"role": "assistant", "content": ai_msg})
|
47 |
messages_for_template.append({"role": "user", "content": message})
|
48 |
|
49 |
try:
|
|
|
50 |
prompt = tokenizer.apply_chat_template(
|
51 |
messages_for_template,
|
52 |
tokenize=False,
|
53 |
+
add_generation_prompt=True
|
54 |
)
|
55 |
except Exception as e:
|
56 |
print(f"Fehler beim Anwenden des Chat-Templates: {e}")
|
|
|
57 |
prompt_parts = []
|
58 |
for turn in messages_for_template:
|
59 |
prompt_parts.append(f"<|im_start|>{turn['role']}\n{turn['content']}<|im_end|>")
|
60 |
prompt = "\n".join(prompt_parts) + "\n<|im_start|>assistant\n"
|
61 |
|
|
|
62 |
inputs = tokenizer(prompt, return_tensors="pt", padding=True, truncation=True).to("cpu")
|
63 |
|
|
|
64 |
generation_kwargs = {
|
65 |
"max_new_tokens": 512,
|
66 |
"temperature": 0.7,
|
67 |
"top_p": 0.9,
|
68 |
"top_k": 50,
|
69 |
"do_sample": True,
|
70 |
+
"pad_token_id": tokenizer.eos_token_id,
|
71 |
}
|
72 |
|
73 |
print("Generiere Antwort...")
|
|
|
74 |
with torch.no_grad():
|
75 |
outputs = model.generate(**inputs, **generation_kwargs)
|
76 |
|
|
|
77 |
response_ids = outputs[0][inputs.input_ids.shape[-1]:]
|
78 |
response = tokenizer.decode(response_ids, skip_special_tokens=True)
|
|
|
79 |
print(f"Antwort: {response}")
|
|
|
|
|
|
|
80 |
return response
|
81 |
|
82 |
# --- Gradio UI ---
|
|
|
83 |
with gr.Blocks(theme=gr.themes.Soft(), title="DeepSeek Qwen3 8B (CPU)") as demo:
|
84 |
gr.Markdown(
|
85 |
"""
|
|
|
89 |
Bitte habe Geduld.
|
90 |
"""
|
91 |
)
|
|
|
92 |
chatbot_interface = gr.ChatInterface(
|
93 |
fn=predict,
|
94 |
chatbot=gr.Chatbot(
|
95 |
height=600,
|
96 |
label="Chat",
|
97 |
+
show_label=False,
|
98 |
+
# bubble_full_width=False, # Entfernt, da veraltet
|
99 |
+
# type="messages" # Wichtig, um die Warnung zu beheben, aber history-Format in predict() muss passen
|
100 |
+
# Da predict bereits die history als [[user, ai], [user, ai]] erwartet (Standard für ChatInterface),
|
101 |
+
# lassen wir type hier weg, damit es mit dem Format von predict harmoniert.
|
102 |
+
# Wenn predict `history` als [{"role": "user", ...}, {"role": "assistant", ...}] erwarten würde,
|
103 |
+
# dann wäre `type="messages"` hier richtig.
|
104 |
+
# Da die Warnung sich auf die Standardeinstellung bezieht, die bald "messages" sein wird,
|
105 |
+
# und unsere predict-Funktion bereits das "tuples"-Format verarbeitet, ist das OK für jetzt.
|
106 |
+
# Man könnte predict anpassen, um das "messages" Format direkt zu verarbeiten, wenn man type="messages" setzt.
|
107 |
),
|
108 |
textbox=gr.Textbox(
|
109 |
placeholder="Stelle mir eine Frage...",
|
110 |
+
container=False,
|
111 |
+
scale=7
|
112 |
),
|
|
|
|
|
113 |
examples=[
|
114 |
["Hallo, wer bist du?"],
|
115 |
["Was ist die Hauptstadt von Frankreich?"],
|
116 |
["Schreibe ein kurzes Gedicht über KI."]
|
117 |
],
|
118 |
+
# Entferne die nicht unterstützten Button-Argumente:
|
119 |
+
# retry_btn="Wiederholen",
|
120 |
+
# undo_btn="Letzte entfernen",
|
121 |
+
# clear_btn="Chat löschen",
|
122 |
)
|
123 |
gr.Markdown("Modell von [deepseek-ai](https://huggingface.co/deepseek-ai) auf Hugging Face.")
|
124 |
|
|
|
|
|
125 |
if __name__ == "__main__":
|
|
|
|
|
126 |
demo.launch()
|