LucanDerLurch commited on
Commit
866e648
·
verified ·
1 Parent(s): 4eca839

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +101 -40
app.py CHANGED
@@ -5,29 +5,30 @@ from huggingface_hub import InferenceClient
5
  # Token aus den Hugging Face Secrets laden
6
  token = os.environ.get("HF_TOKEN")
7
  text_client = InferenceClient("google/gemma-1.1-7b-it", token=token)
8
- bild_client = InferenceClient("stabilityai/stable-diffusion-xl-base-1.0", token=token)
 
9
 
10
  # Unser neues, ultra-atmosphärisches CSS (Gestaltungscode)
 
11
  geiles_design = """
12
  @import url('https://fonts.googleapis.com/css2?family=Special+Elite&display=swap');
13
 
14
  body, .gradio-container {
15
- /* Düsteres Apokalypse-Hintergrundbild aus dem Netz */
16
- background-image: url('https://images.unsplash.com/photo-1485603099951-40344d18721c?q=80&w=2000&auto=format&fit=crop') !important;
17
  background-size: cover !important;
18
  background-position: center !important;
19
  background-attachment: fixed !important;
20
  font-family: sans-serif;
21
  }
22
 
23
- /* Der Hauptbereich wird schwarz und leicht durchsichtig */
24
  .haupt-bereich {
25
  background: rgba(0, 0, 0, 0.7) !important;
26
  border-radius: 10px;
27
  padding: 20px !important;
28
  max-width: 800px !important;
29
  margin: 0 auto !important;
30
- backdrop-filter: blur(3px); /* Macht das Hintergrundbild leicht unscharf */
31
  border: 1px solid rgba(255, 255, 255, 0.1);
32
  }
33
 
@@ -45,25 +46,47 @@ h1 { color: #d4af37 !important; text-align: center; text-transform: uppercase; f
45
  font-weight: bold;
46
  }
47
 
48
- /* Der Notizzettel für die Story! */
49
- .notizzettel {
50
- background: #e3dec6 !important; /* Schmutzige Papier-Farbe */
 
 
 
 
 
 
 
 
 
 
 
51
  color: #1a1a1a !important;
52
- font-family: 'Special Elite', monospace !important; /* Echte Schreibmaschinen-Schrift */
53
  font-size: 1.3em !important;
54
  line-height: 1.6 !important;
55
- padding: 25px !important;
56
  border-radius: 2px !important;
57
- box-shadow: 3px 3px 15px rgba(0,0,0,0.8) !important;
58
- transform: rotate(-1deg); /* Leichte Drehung für den echten Zettel-Look */
59
- margin: 20px 5px !important;
60
- border-left: 4px solid #8b0000 !important; /* Roter Rand */
61
  }
62
 
63
- /* Rahmen für das generierte Bild */
64
- .output-bild { border: 2px solid #555 !important; border-radius: 3px !important; box-shadow: 0 5px 15px rgba(0,0,0,0.9) !important;}
 
 
 
 
 
65
 
66
- /* Eingabefeld durchsichtig machen */
 
 
 
 
 
 
67
  input, textarea {
68
  background: rgba(0, 0, 0, 0.6) !important;
69
  color: #fff !important;
@@ -72,7 +95,6 @@ input, textarea {
72
  border-radius: 5px !important;
73
  }
74
 
75
- /* Aggressiver Action-Button */
76
  button {
77
  background: #8b0000 !important;
78
  color: #fff !important;
@@ -87,73 +109,112 @@ button {
87
  button:hover { background: #aa0000 !important; }
88
  """
89
 
90
- def spiel_zug(nachricht, aktueller_rucksack):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
  if not nachricht:
92
- return None, "Der Zettel ist leer. Du musst schon etwas tun!", aktueller_rucksack, f"🎒 INVENTAR: {aktueller_rucksack}", ""
 
93
 
 
94
  system_prompt = f"""Du bist 'Zombie Go'.
95
  Inventar des Spielers: {aktueller_rucksack}.
96
- Regel: Der Spieler darf NUR Dinge nutzen, die im Inventar sind.
97
- Aktion: '{nachricht}'.
98
 
99
- Antworte in diesem Format:
100
- STORY: [Max 3 Sätze, düster, beschreibe die Folgen der Aktion]
101
- RUCKSACK: [Aktualisierte Liste der Items] | GO: [Anzahl]"""
102
 
103
  try:
104
- antwort = text_client.text_generation(system_prompt, max_new_tokens=200)
105
 
 
106
  if "RUCKSACK:" in antwort:
107
  teile = antwort.split("RUCKSACK:")
108
  story_text = teile[0].replace("STORY:", "").strip()
109
  neuer_rucksack = teile[1].strip()
110
  else:
 
111
  story_text = antwort.replace("STORY:", "").strip()
112
  neuer_rucksack = aktueller_rucksack
 
113
  except Exception as e:
114
- story_text = "Der Stift bricht ab... Schreibblockade. (Verbindung zur KI unterbrochen)"
115
  neuer_rucksack = aktueller_rucksack
116
 
117
- bild_prompt = f"dark zombie apocalypse survival scene, first person view, {nachricht}, eerie lighting, ruined city, highly detailed, realistic texture"
 
 
 
 
 
 
 
118
  try:
119
- bild = bild_client.text_to_image(bild_prompt)
 
120
  except:
121
  bild = None
122
 
123
  rucksack_ui_text = f"🎒 INVENTAR: {neuer_rucksack}"
124
 
125
- return bild, story_text, neuer_rucksack, rucksack_ui_text, ""
 
126
 
127
 
 
128
  with gr.Blocks(css=geiles_design, theme=gr.themes.Base()) as spiel_oberflaeche:
129
  with gr.Column(elem_classes="haupt-bereich"):
130
  gr.Markdown("# 🧟 ZOMBIE GO")
131
 
132
- # Der Start-Rucksack
 
133
  rucksack_speicher = gr.State("Brecheisen, leere Wasserflasche | GO: 0")
 
 
134
  rucksack_ui = gr.Markdown("🎒 INVENTAR: Brecheisen, leere Wasserflasche | GO: 0", elem_classes="rucksack-anzeige")
135
 
136
- # Das Bild
137
  szene_bild = gr.Image(label="Visuelles Echo", type="pil", elem_classes="output-bild")
138
 
139
- # HIER IST DEIN START-TEXT AUF DEM NOTIZZETTEL
140
- start_text = "Tag 1. Mein Kopf dröhnt. Ich bin in einem verlassenen Supermarkt aufgewacht. Die Regale sind geplündert, draußen brennen Autos. Ich höre ein ekliges Kratzen an den vernagelten Fenstern. Neben mir liegt ein altes Brecheisen. Ich muss hier raus..."
141
- story_ausgabe = gr.Markdown(start_text, elem_classes="notizzettel")
142
 
143
  gr.Markdown("---")
144
 
145
- eingabe = gr.Textbox(label="", placeholder="Was tust du? (z.B. Ich schleiche zur Tür)", lines=1)
 
146
  senden_btn = gr.Button("▶ AKTION EINTRAGEN")
147
 
 
 
148
  senden_btn.click(
149
  spiel_zug,
150
- inputs=[eingabe, rucksack_speicher],
151
- outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe]
152
  )
153
  eingabe.submit(
154
  spiel_zug,
155
- inputs=[eingabe, rucksack_speicher],
156
- outputs=[szene_bild, story_ausgabe, rucksack_speicher, rucksack_ui, eingabe]
157
  )
158
 
 
159
  spiel_oberflaeche.launch()
 
5
  # Token aus den Hugging Face Secrets laden
6
  token = os.environ.get("HF_TOKEN")
7
  text_client = InferenceClient("google/gemma-1.1-7b-it", token=token)
8
+ # Wir nutzen SDXL Turbo für extrem schnelle Bilder am Handy!
9
+ bild_client = InferenceClient("stabilityai/sdxl-turbo", token=token)
10
 
11
  # Unser neues, ultra-atmosphärisches CSS (Gestaltungscode)
12
+ # Wir fügen die Styles für das gestapelte Logbuch hinzu.
13
  geiles_design = """
14
  @import url('https://fonts.googleapis.com/css2?family=Special+Elite&display=swap');
15
 
16
  body, .gradio-container {
17
+ /* Lädt das Bild DIREKT von deinem eigenen Hugging Face Space! */
18
+ background-image: url('file/image.png') !important;
19
  background-size: cover !important;
20
  background-position: center !important;
21
  background-attachment: fixed !important;
22
  font-family: sans-serif;
23
  }
24
 
 
25
  .haupt-bereich {
26
  background: rgba(0, 0, 0, 0.7) !important;
27
  border-radius: 10px;
28
  padding: 20px !important;
29
  max-width: 800px !important;
30
  margin: 0 auto !important;
31
+ backdrop-filter: blur(2px);
32
  border: 1px solid rgba(255, 255, 255, 0.1);
33
  }
34
 
 
46
  font-weight: bold;
47
  }
48
 
49
+ /* Rahmen für das generierte Bild */
50
+ .output-bild { border: 2px solid #555 !important; border-radius: 3px !important; box-shadow: 0 5px 15px rgba(0,0,0,0.9) !important;}
51
+
52
+ /* --- Das Logbuch --- */
53
+ /* Dies ist der Container für den Chat-Verlauf, der wie ein Stapel Notizen aussieht */
54
+ .logbuch-stapel {
55
+ margin: 20px 0 !important;
56
+ height: 400px !important;
57
+ overflow-y: scroll !important; /* Scrollen, wenn der Stapel zu lang wird */
58
+ }
59
+
60
+ /* Jeder Eintrag (dein Text ODER der KI-Text) wird zu einem eigenen Notizzettel */
61
+ .notizzettel-eintrag {
62
+ background: #e3dec6 !important;
63
  color: #1a1a1a !important;
64
+ font-family: 'Special Elite', monospace !important;
65
  font-size: 1.3em !important;
66
  line-height: 1.6 !important;
67
+ padding: 15px !important;
68
  border-radius: 2px !important;
69
+ box-shadow: 2px 2px 10px rgba(0,0,0,0.8) !important;
70
+ margin-bottom: -15px !important; /* Stapelungseffekt */
71
+ position: relative !important;
72
+ border-left: 4px solid #8b0000 !important;
73
  }
74
 
75
+ /* Deine Notizen sind links */
76
+ .user-notiz {
77
+ transform: rotate(0.5deg);
78
+ margin-right: 15% !important;
79
+ border-left-color: #d4af37 !important;
80
+ opacity: 0.9;
81
+ }
82
 
83
+ /* Die Notizen der KI sind rechts */
84
+ .ai-notiz {
85
+ transform: rotate(-0.5deg);
86
+ margin-left: 15% !important;
87
+ }
88
+
89
+ /* --- Eingabe --- */
90
  input, textarea {
91
  background: rgba(0, 0, 0, 0.6) !important;
92
  color: #fff !important;
 
95
  border-radius: 5px !important;
96
  }
97
 
 
98
  button {
99
  background: #8b0000 !important;
100
  color: #fff !important;
 
109
  button:hover { background: #aa0000 !important; }
110
  """
111
 
112
+ # Eine Hilfsfunktion, die den Chat-Verlauf in HTML-Notizzettel umwandelt
113
+ def generiere_logbuch_html(verlauf):
114
+ html = '<div class="logbuch-stapel">'
115
+ # Start-Text hinzufügen, wenn der Verlauf leer ist
116
+ if not verlauf:
117
+ start_text = "Tag 1. Mein Kopf dröhnt. Ich bin in einem verlassenen Supermarkt aufgewacht. Die Regale sind geplündert, draußen brennen Autos. Ich höre ein ekliges Kratzen an den vernagelten Fenstern. Neben mir liegt ein altes Brecheisen. Ich muss hier raus..."
118
+ html += f'<div class="notizzettel-eintrag ai-notiz"> {start_text} </div>'
119
+ else:
120
+ # Den Verlauf durchgehen und Notizen stapeln
121
+ for user_text, ai_text in verlauf:
122
+ if user_text:
123
+ html += f'<div class="notizzettel-eintrag user-notiz"> {user_text} </div>'
124
+ if ai_text:
125
+ html += f'<div class="notizzettel-eintrag ai-notiz"> {ai_text} </div>'
126
+ html += '</div>'
127
+ return html
128
+
129
+ def spiel_zug(nachricht, verlauf, aktueller_rucksack):
130
  if not nachricht:
131
+ return (generiere_logbuch_html(verlauf), verlauf, None, aktueller_rucksack,
132
+ f"🎒 INVENTAR: {aktueller_rucksack}", "")
133
 
134
+ # Die KI soll die Story UND den Rucksack verwalten
135
  system_prompt = f"""Du bist 'Zombie Go'.
136
  Inventar des Spielers: {aktueller_rucksack}.
137
+ Regel: Der Spieler darf NUR Dinge nutzen, die im Inventar sind. Erfinde keine Waffen für ihn.
138
+ Aktion des Spielers: '{nachricht}'.
139
 
140
+ Antworte EXAKT in dieser Form (ohne Ausnahmen):
141
+ STORY: [Beschreibe in max 3 spannenden Sätzen, was passiert. Füge neu gefundene Gegenstände logisch zum Rucksack hinzu.]
142
+ RUCKSACK: [Liste der Items] | GO: [Anzahl]"""
143
 
144
  try:
145
+ antwort = text_client.text_generation(system_prompt, max_new_tokens=250)
146
 
147
+ # Split (Text zerteilen): Wir trennen Story und Rucksack am Wort "RUCKSACK:"
148
  if "RUCKSACK:" in antwort:
149
  teile = antwort.split("RUCKSACK:")
150
  story_text = teile[0].replace("STORY:", "").strip()
151
  neuer_rucksack = teile[1].strip()
152
  else:
153
+ # Falls die KI den Befehl vermasselt, behalten wir den alten Rucksack
154
  story_text = antwort.replace("STORY:", "").strip()
155
  neuer_rucksack = aktueller_rucksack
156
+
157
  except Exception as e:
158
+ story_text = "Die Tinte versagt... (Verbindung zur KI unterbrochen)"
159
  neuer_rucksack = aktueller_rucksack
160
 
161
+ # Den Chat-Verlauf aktualisieren
162
+ verlauf.append((nachricht, story_text))
163
+
164
+ # Das Logbuch-HTML neu generieren (inklusive neuer Aktionen)
165
+ logbuch_html = generiere_logbuch_html(verlauf)
166
+
167
+ # Bild-KI (SDXL Turbo - EXTREM SCHNELL!)
168
+ bild_prompt = f"dark zombie apocalypse survival scene, first person view, {nachricht}, eerie green lighting from glowing crystals, highly detailed, realistic texture, derelict ruined city, atmospheric"
169
  try:
170
+ # SDXL Turbo braucht extrem wenige Schritte und ist fast sofort fertig!
171
+ bild = bild_client.text_to_image(bild_prompt, num_inference_steps=1)
172
  except:
173
  bild = None
174
 
175
  rucksack_ui_text = f"🎒 INVENTAR: {neuer_rucksack}"
176
 
177
+ # Gibt alles zurück: Logbuch, Chat-History (gr.State), Bild, leeres Textfeld, schicke Rucksack-Anzeige, unsichtbarer Rucksack-Speicher
178
+ return logbuch_html, verlauf, bild, "", rucksack_ui_text, neuer_rucksack
179
 
180
 
181
+ # Wir laden das eigene CSS direkt in den Baukasten
182
  with gr.Blocks(css=geiles_design, theme=gr.themes.Base()) as spiel_oberflaeche:
183
  with gr.Column(elem_classes="haupt-bereich"):
184
  gr.Markdown("# 🧟 ZOMBIE GO")
185
 
186
+ # Unsichtbare Speicher (gr.State)
187
+ chat_verlauf = gr.State([]) # Speichert den kompletten Verlauf
188
  rucksack_speicher = gr.State("Brecheisen, leere Wasserflasche | GO: 0")
189
+
190
+ # Die sichtbare Anzeige für das Inventar
191
  rucksack_ui = gr.Markdown("🎒 INVENTAR: Brecheisen, leere Wasserflasche | GO: 0", elem_classes="rucksack-anzeige")
192
 
193
+ # Das generierte Bild
194
  szene_bild = gr.Image(label="Visuelles Echo", type="pil", elem_classes="output-bild")
195
 
196
+ # Das Logbuch (HTML Container für die gestapelten Notizen)
197
+ # Wir rufen direkt am Anfang die Funktion auf, um den Start-Text zu zeigen.
198
+ logbuch_ui = gr.HTML(generiere_logbuch_html([]), elem_classes="logbuch-stapel")
199
 
200
  gr.Markdown("---")
201
 
202
+ # Eingabe-Bereich
203
+ eingabe = gr.Textbox(label="", placeholder="Was tust du? (z.B. Umschauen)", lines=1)
204
  senden_btn = gr.Button("▶ AKTION EINTRAGEN")
205
 
206
+ # Verknüpfungen der Knöpfe (wichtige Reihenfolge der Outputs!)
207
+ # Wir aktualisieren jetzt das logbuch_ui und chat_verlauf
208
  senden_btn.click(
209
  spiel_zug,
210
+ inputs=[eingabe, chat_verlauf, rucksack_speicher],
211
+ outputs=[logbuch_ui, chat_verlauf, szene_bild, eingabe, rucksack_ui, rucksack_speicher]
212
  )
213
  eingabe.submit(
214
  spiel_zug,
215
+ inputs=[eingabe, chat_verlauf, rucksack_speicher],
216
+ outputs=[logbuch_ui, chat_verlauf, szene_bild, eingabe, rucksack_ui, rucksack_speicher]
217
  )
218
 
219
+ # Startet das Game
220
  spiel_oberflaeche.launch()