MatteoScript commited on
Commit
90c5698
·
verified ·
1 Parent(s): 2f9c799

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +118 -45
app.py CHANGED
@@ -24,7 +24,7 @@ ambientazioni = {
24
  "Sacro Romano Impero": {
25
  "nome": "Sacro Romano Impero",
26
  "stile_immagine": (
27
- "Highly detailed, painterly style with a historical yet stylized aesthetic. "
28
  "Rich textures, ornate patterns, and a color palette dominated by imperial gold, "
29
  "deep red, and aged marble tones. Inspired by medieval European art, "
30
  "gothic illuminations, and the grandeur of cathedrals. "
@@ -92,39 +92,46 @@ ambientazioni = {
92
  "Cowboy del Far West": {
93
  "nome": "Cowboy del Far West",
94
  "stile_immagine": (
95
- "Uno stile che richiama i paesaggi desertici, le praterie sconfinate e i tramonti infuocati. "
96
- "Elementi iconici come cappelli da cowboy, revolver e diligenze, uniti a colori terrosi e caldi. "
97
- "Una composizione che unisce il romanticismo dell'Ovest selvaggio a un design chiaro e narrativo, "
98
- "ideale per illustrare scene di duelli e viaggi avventurosi."
 
99
  )
100
  },
101
  "Steampunk": {
102
  "nome": "Steampunk",
103
  "stile_immagine": (
104
- "Un'estetica retrofuturistica che fonde l'epoca vittoriana con invenzioni meccaniche. "
105
- "Abiti d'epoca, ingranaggi in ottone, macchinari complessi e ambientazioni industriali. "
106
- "Colori caldi e metallici, texture invecchiate e dettagli elaborati che trasmettono un'atmosfera "
107
- "di mistero e innovazione, perfetti per una carta di gioco che vuole raccontare storie fuori dal comune."
 
 
108
  )
109
  },
110
  "Alieni": {
111
  "nome": "Alieni",
112
  "stile_immagine": (
113
- "Un'estetica fantascientifica e surreale, con creature d'aspetto extraterrestre, "
114
- "paesaggi cosmici e tecnologie aliene. Combina elementi di luce fluorescente, "
115
- "forme organiche e architetture impossibili, creando un'atmosfera misteriosa e intrigante. "
116
- "Ideale per un gioco di carte che trasporta i giocatori in un universo lontano e pieno di meraviglie."
 
 
117
  )
118
  },
119
  "Homo Sapiens": {
120
  "nome": "Homo Sapiens",
121
  "stile_immagine": (
122
- "Un'interpretazione moderna e riflessiva dell'evoluzione umana, con un mix di realismo e "
123
- "elementi simbolici che rappresentano la storia e la cultura della nostra specie. "
124
- "Utilizza toni naturali, texture ispirate alla materia organica e dettagli che richiamano "
125
- "l'arte preistorica e contemporanea, per creare un'immagine che unisce il passato remoto al presente."
 
 
126
  )
127
- },
128
  }
129
 
130
 
@@ -137,12 +144,27 @@ class Character(BaseModel):
137
  intelligenza: int
138
  descrizione: str
139
  english_description:str
 
140
 
141
  # Definizione dello schema per la risposta contenente una lista di personaggi
142
  class CharactersResponse(BaseModel):
143
  personaggi: list[Character]
144
 
145
- def generate_story(character: Character, nome_ambientazione, creativita):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  response = clientOpenAI.chat.completions.create(
147
  model='gemini-2.0-flash-thinking-exp-01-21',
148
  n=1,
@@ -152,7 +174,7 @@ def generate_story(character: Character, nome_ambientazione, creativita):
152
  {"role": "system", "content": f"Tu sei un creatore di giochi di ruolo a CARTE. Crea un regolamento per un gioco di ruolo sul {nome_ambientazione} sulla base dei personaggi che ti fornirò"},
153
  {
154
  "role": "user",
155
- "content": f"Ecco i personaggi del gioco di RUOLO a carte. Crea un regolamento!!! {character.model_dump_json()}"
156
  }
157
  ]
158
  )
@@ -170,8 +192,9 @@ def generate_story(character: Character, nome_ambientazione, creativita):
170
  def generate_ai(num_personaggi, nome_ambientazione, creativita):
171
  # Costruzione del prompt in italiano per generare i personaggi
172
  prompt = (
173
- f"Genera {num_personaggi} personaggi per un gioco di ruolo a carte ambientato nel {nome_ambientazione}. "
174
- "Ogni personaggio deve avere i seguenti campi specificati nel modello. "
 
175
  "Restituisci il risultato in formato JSON seguendo lo schema fornito")
176
 
177
  # Esecuzione della chiamata all'API utilizzando il formato response_format
@@ -188,6 +211,24 @@ def generate_ai(num_personaggi, nome_ambientazione, creativita):
188
  print(characters_response)
189
  return characters_response
190
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
191
  # Funzione per generare le immagini, con gestione errori e retry dopo 10 secondi
192
  def generate_image(prompt, max_retries=5):
193
  client = Together(api_key=api_together)
@@ -205,19 +246,33 @@ def generate_image(prompt, max_retries=5):
205
  )
206
  return response.data # Una lista di oggetti con attributo b64_json
207
  except Exception as e:
208
- st.error(f"Errore durante la generazione delle immagini: {e}. Riprovo tra 10 secondi...")
209
- time.sleep(10)
210
  retries += 1
211
  st.error("Numero massimo di tentativi raggiunto. Impossibile generare le immagini.")
212
  return None
213
 
214
- def generate_images(character: Character, stile_immagine, num_immagini):
215
  # Lista per salvare le immagini generate come tuple (nome_file, bytes)
216
- prompt = f"{character.english_description} {stile_immagine}. (INSERT TEXT NAME = {character.nome})"
217
- images_bytes_list = []
218
- if character.nome != "":
219
- st.subheader(f"{character.nome} 🦸‍♂️")
220
- st.markdown(f"- **Classe:** {character.classe}\n- **Forza:** {character.forza}\n- **Destrezza:** {character.destrezza}\n- **Intelligenza:** {character.intelligenza}\n- **Descrizione:** {character.descrizione}", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  for numero in range(num_immagini):
222
  images_data = generate_image(prompt)
223
  if images_data is not None:
@@ -233,7 +288,7 @@ def generate_images(character: Character, stile_immagine, num_immagini):
233
  st.error(f"Errore nella visualizzazione dell'immagine {i+1}: {e}")
234
  else:
235
  st.error("Non è stato possibile generare le immagini. Riprova più tardi.")
236
- time.sleep(5)
237
  return images_bytes_list
238
 
239
  def main():
@@ -245,32 +300,50 @@ def main():
245
  stile_immagine = st.sidebar.text_area("Stile Immagine", stile_default, disabled=False)
246
  auto = False
247
  prompt_input = st.sidebar.text_input("Prompt Immagine (in inglese)", value="Soldier", disabled=auto)
248
- auto = st.sidebar.toggle(label= 'Generazione automatica', value = True)
249
- num_personaggi = st.sidebar.slider("Personaggi", min_value=1, max_value=30, value=5, disabled=not auto)
250
  num_immagini = st.sidebar.slider("Variazioni Immagini", min_value=1, max_value=6, value=2)
 
 
 
 
251
  creativita = st.sidebar.slider("Creativita", min_value=0.1, max_value=1.0, value=0.8, step=0.1)
252
  submit_button = st.sidebar.button(label="Genera Immagine", type="primary", use_container_width=True)
253
- st.write("Forgia il tuo **destino nell'Impero**: crea, combatti e domina con nel più grande gioco di ruolo a carte generato dall'AI")
254
 
255
  if submit_button:
256
  if not prompt_input.strip() and not auto:
257
  st.error("Per favore, inserisci un prompt per l'immagine!")
258
  return
 
 
259
  if auto:
260
- with st.spinner('Generazione Personaggi'):
261
- characters = generate_ai(num_personaggi, nome_ambientazione, creativita)
262
- st.subheader('Personaggi 🎭')
263
- df = pd.DataFrame([{k: v for k, v in character.model_dump().items() if k != "english_description"} for character in characters.personaggi])
264
- st.dataframe(df, hide_index=True)
265
- st.divider()
266
- generate_story(characters, nome_ambientazione, creativita)
267
- st.divider()
 
 
 
 
 
 
 
 
 
 
268
  else:
269
- characters = CharactersResponse(personaggi=[Character(nome="", classe="Guerriero", forza=10, destrezza=8, intelligenza=6, descrizione="Un forte guerriero", english_description=prompt_input)])
270
  with st.spinner('Generazione Immagini'):
271
  images = []
272
- for character in characters.personaggi:
273
- images.extend(generate_images(character, stile_immagine, num_immagini))
 
 
 
 
274
  if images:
275
  zip_buffer = io.BytesIO()
276
  with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file:
 
24
  "Sacro Romano Impero": {
25
  "nome": "Sacro Romano Impero",
26
  "stile_immagine": (
27
+ "In the italian Holy Roman Empire, Highly detailed, painterly style with a historical yet stylized aesthetic. "
28
  "Rich textures, ornate patterns, and a color palette dominated by imperial gold, "
29
  "deep red, and aged marble tones. Inspired by medieval European art, "
30
  "gothic illuminations, and the grandeur of cathedrals. "
 
92
  "Cowboy del Far West": {
93
  "nome": "Cowboy del Far West",
94
  "stile_immagine": (
95
+ "Highly detailed, painterly style with a rugged yet cinematic aesthetic. "
96
+ "Rich textures, earthy tones, and a palette dominated by dusty browns, deep reds, and sunset golds. "
97
+ "Inspired by classic Western art, frontier landscapes, and vintage posters. "
98
+ "Iconic elements like cowboy hats, revolvers, and stagecoaches evoke the romance of the Wild West. "
99
+ "Designed for a tabletop card game, ensuring clarity, readability, and an immersive sense of adventure."
100
  )
101
  },
102
  "Steampunk": {
103
  "nome": "Steampunk",
104
  "stile_immagine": (
105
+ "Highly detailed, painterly style with a fusion of Victorian elegance and mechanical ingenuity. "
106
+ "Brass gears, intricate machinery, steam-powered contraptions, and industrial backdrops "
107
+ "create a retro-futuristic atmosphere. "
108
+ "A color palette dominated by warm metallics, deep browns, and aged parchment tones. "
109
+ "Inspired by classic steampunk literature and art, ensuring a visually immersive experience "
110
+ "for a tabletop card game with a sense of mystery and innovation."
111
  )
112
  },
113
  "Alieni": {
114
  "nome": "Alieni",
115
  "stile_immagine": (
116
+ "Highly detailed, painterly style with a futuristic and surreal aesthetic. "
117
+ "Glowing neon hues, organic and biomechanical forms, and impossible cosmic landscapes "
118
+ "blend to create an otherworldly atmosphere. "
119
+ "A color palette dominated by electric blues, deep purples, and iridescent greens. "
120
+ "Inspired by sci-fi concept art and space opera visuals, ensuring clarity, readability, "
121
+ "and a visually stunning experience for a tabletop card game set in a mysterious universe."
122
  )
123
  },
124
  "Homo Sapiens": {
125
  "nome": "Homo Sapiens",
126
  "stile_immagine": (
127
+ "Highly detailed, painterly style with a blend of realism and symbolic representation. "
128
+ "Natural tones, textures inspired by organic matter, and visual elements reflecting "
129
+ "human evolution, history, and cultural development. "
130
+ "A fusion of prehistoric cave paintings, Renaissance anatomical studies, and modern artistic interpretations. "
131
+ "Designed for a tabletop card game, ensuring clarity, readability, and a thought-provoking visual narrative "
132
+ "that bridges the ancient past with the present."
133
  )
134
+ }
135
  }
136
 
137
 
 
144
  intelligenza: int
145
  descrizione: str
146
  english_description:str
147
+ storia: str
148
 
149
  # Definizione dello schema per la risposta contenente una lista di personaggi
150
  class CharactersResponse(BaseModel):
151
  personaggi: list[Character]
152
 
153
+ class ActionCard(BaseModel):
154
+ nome_azione: str
155
+ breve_descrizione: str
156
+ breve_descrizione_inglese: str
157
+
158
+ class ActionCardsResponse(BaseModel):
159
+ carte_azione: list[ActionCard]
160
+
161
+ def generate_story(character: Character, carte_azione: ActionCardsResponse, nome_ambientazione, creativita):
162
+ descrizione_carte_azione = ""
163
+ descrizione_personaggi = ""
164
+ if carte_azione:
165
+ descrizione_carte_azione = f"Ecco anche le CARTE AZIONE del gioco: {carte_azione.model_dump_json()}"
166
+ if character:
167
+ descrizione_personaggi = f"Ecco i personaggi del gioco di RUOLO a carte. {character.model_dump_json()}"
168
  response = clientOpenAI.chat.completions.create(
169
  model='gemini-2.0-flash-thinking-exp-01-21',
170
  n=1,
 
174
  {"role": "system", "content": f"Tu sei un creatore di giochi di ruolo a CARTE. Crea un regolamento per un gioco di ruolo sul {nome_ambientazione} sulla base dei personaggi che ti fornirò"},
175
  {
176
  "role": "user",
177
+ "content": f"Crea un regolamento!!! {descrizione_personaggi} \n\n {descrizione_carte_azione}"
178
  }
179
  ]
180
  )
 
192
  def generate_ai(num_personaggi, nome_ambientazione, creativita):
193
  # Costruzione del prompt in italiano per generare i personaggi
194
  prompt = (
195
+ f"Genera {num_personaggi} personaggi AMBIENTATI NELL'EPOCA {nome_ambientazione}, per un gioco di ruolo a carte."
196
+ "Ogni personaggio deve avere i seguenti campi specificati nel modello ed devono essere COERENTI con l'epoca e l'ambientazione fornita (per esempio, se siamo nel Sacro Romano Impero devono essere nomi italiani) "
197
+ "nel campo STORIA, inventa la una BREVE storia di background del personaggio specificando aneddoti, e altre cose che rendono il personaggio unico. "
198
  "Restituisci il risultato in formato JSON seguendo lo schema fornito")
199
 
200
  # Esecuzione della chiamata all'API utilizzando il formato response_format
 
211
  print(characters_response)
212
  return characters_response
213
 
214
+ def generate_card_ai(num_carte_azione, nome_ambientazione, creativita):
215
+ prompt = (
216
+ f"Genera {num_carte_azione} CARTE AZIONE, per un gioco di ruolo ambientato in {nome_ambientazione}. "
217
+ "Attieniti allo schema formito e sii molto SINTETICO")
218
+
219
+ # Esecuzione della chiamata all'API utilizzando il formato response_format
220
+ completion = clientOpenAI.beta.chat.completions.parse(
221
+ model=MODEL,
222
+ messages=[
223
+ {"role": "system", "content": f"Sei un assistente utile per la generazione di CARTE AZIONE per un gioco di RUOLO sul {nome_ambientazione}."},
224
+ {"role": "user", "content": prompt},
225
+ ],
226
+ temperature=creativita,
227
+ response_format=ActionCardsResponse,
228
+ )
229
+ action_card_response = completion.choices[0].message.parsed
230
+ return action_card_response
231
+
232
  # Funzione per generare le immagini, con gestione errori e retry dopo 10 secondi
233
  def generate_image(prompt, max_retries=5):
234
  client = Together(api_key=api_together)
 
246
  )
247
  return response.data # Una lista di oggetti con attributo b64_json
248
  except Exception as e:
249
+ print(f"Errore durante la generazione delle immagini: {e}. Riprovo tra 10 secondi...")
250
+ time.sleep(9)
251
  retries += 1
252
  st.error("Numero massimo di tentativi raggiunto. Impossibile generare le immagini.")
253
  return None
254
 
255
+ def generate_images(character: Character, carta_azione: ActionCard, stile_immagine, num_immagini):
256
  # Lista per salvare le immagini generate come tuple (nome_file, bytes)
257
+ if character:
258
+ prompt = f"{character.english_description} {stile_immagine}. (INSERT TEXT NAME = {character.nome})"
259
+ images_bytes_list = []
260
+ if character.nome != "":
261
+ st.subheader(f"{character.nome} 🦸‍♂️")
262
+ st.write(
263
+ f"- **Classe:** {character.classe}\n"
264
+ f"- **Forza:** {character.forza}\n"
265
+ f"- **Destrezza:** {character.destrezza}\n"
266
+ f"- **Intelligenza:** {character.intelligenza}\n"
267
+ f"- **Descrizione:** {character.descrizione}\n",
268
+ f"- **Storia:** {character.storia}"
269
+ )
270
+ if carta_azione:
271
+ prompt = f"PLAYING CARD FOR A CARD GAME WITHOUT CHARACTER WITH THIS BOLD INSCRIPTION IN THE CENTER OF THE CARD: '{carta_azione.nome_azione}'. USE THIS STYLE: {stile_immagine}.)"
272
+ images_bytes_list = []
273
+ st.subheader(f"{carta_azione.nome_azione} 🃏")
274
+ st.write(f"- **Descrizione:** {carta_azione.breve_descrizione}")
275
+ print(prompt)
276
  for numero in range(num_immagini):
277
  images_data = generate_image(prompt)
278
  if images_data is not None:
 
288
  st.error(f"Errore nella visualizzazione dell'immagine {i+1}: {e}")
289
  else:
290
  st.error("Non è stato possibile generare le immagini. Riprova più tardi.")
291
+ time.sleep(0.5)
292
  return images_bytes_list
293
 
294
  def main():
 
300
  stile_immagine = st.sidebar.text_area("Stile Immagine", stile_default, disabled=False)
301
  auto = False
302
  prompt_input = st.sidebar.text_input("Prompt Immagine (in inglese)", value="Soldier", disabled=auto)
 
 
303
  num_immagini = st.sidebar.slider("Variazioni Immagini", min_value=1, max_value=6, value=2)
304
+ auto = st.sidebar.toggle(label= 'Generazione automatica', value = True)
305
+ num_personaggi = st.sidebar.slider("Personaggi", min_value=0, max_value=30, value=5, disabled=not auto)
306
+ num_carte_azione = st.sidebar.slider("Carte Azione", min_value=0, max_value=10, value=0, disabled=not auto)
307
+ genera_regolamento = st.sidebar.toggle(label= 'Regolamento', value = True, disabled=not auto)
308
  creativita = st.sidebar.slider("Creativita", min_value=0.1, max_value=1.0, value=0.8, step=0.1)
309
  submit_button = st.sidebar.button(label="Genera Immagine", type="primary", use_container_width=True)
310
+ st.write("Forgia il tuo **destino nell'Impero**: crea, combatti e domina nel più grande gioco di ruolo a carte generato dall'AI")
311
 
312
  if submit_button:
313
  if not prompt_input.strip() and not auto:
314
  st.error("Per favore, inserisci un prompt per l'immagine!")
315
  return
316
+ carte_azione = None
317
+ characters = None
318
  if auto:
319
+ if num_personaggi > 0:
320
+ with st.spinner('Generazione Personaggi'):
321
+ characters = generate_ai(num_personaggi, nome_ambientazione, creativita)
322
+ st.subheader('Personaggi 🎭')
323
+ df = pd.DataFrame([{k: v for k, v in character.model_dump().items() if k != "english_description"} for character in characters.personaggi])
324
+ st.dataframe(df, hide_index=True, use_container_width=True)
325
+ st.divider()
326
+ if num_carte_azione > 0:
327
+ with st.spinner('Generazione Carte Azione'):
328
+ carte_azione = generate_card_ai(num_carte_azione, nome_ambientazione, creativita)
329
+ st.subheader('Carte Azione 📒')
330
+ df = pd.DataFrame([{k: v for k, v in carta_azione.model_dump().items() if k != "breve_descrizione_inglese"} for carta_azione in carte_azione.carte_azione])
331
+ st.dataframe(df, hide_index=True, use_container_width=True)
332
+ st.divider()
333
+ if genera_regolamento:
334
+ with st.spinner('Generazione Regolamento'):
335
+ generate_story(characters, carte_azione, nome_ambientazione, creativita)
336
+ st.divider()
337
  else:
338
+ characters = CharactersResponse(personaggi=[Character(nome="", classe="Guerriero", forza=10, destrezza=8, intelligenza=6, storia="", descrizione="Un forte guerriero", english_description=prompt_input)])
339
  with st.spinner('Generazione Immagini'):
340
  images = []
341
+ if characters:
342
+ for character in characters.personaggi:
343
+ images.extend(generate_images(character, None, stile_immagine, num_immagini))
344
+ if carte_azione:
345
+ for carta_azione in carte_azione.carte_azione:
346
+ images.extend(generate_images(None, carta_azione, stile_immagine, num_immagini))
347
  if images:
348
  zip_buffer = io.BytesIO()
349
  with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file: