Spaces:
Running
Running
Update app.py
Browse files
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 |
-
"
|
96 |
-
"
|
97 |
-
"
|
98 |
-
"
|
|
|
99 |
)
|
100 |
},
|
101 |
"Steampunk": {
|
102 |
"nome": "Steampunk",
|
103 |
"stile_immagine": (
|
104 |
-
"
|
105 |
-
"
|
106 |
-
"
|
107 |
-
"
|
|
|
|
|
108 |
)
|
109 |
},
|
110 |
"Alieni": {
|
111 |
"nome": "Alieni",
|
112 |
"stile_immagine": (
|
113 |
-
"
|
114 |
-
"
|
115 |
-
"
|
116 |
-
"
|
|
|
|
|
117 |
)
|
118 |
},
|
119 |
"Homo Sapiens": {
|
120 |
"nome": "Homo Sapiens",
|
121 |
"stile_immagine": (
|
122 |
-
"
|
123 |
-
"
|
124 |
-
"
|
125 |
-
"
|
|
|
|
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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"
|
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
|
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 |
-
|
209 |
-
time.sleep(
|
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 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
-
|
273 |
-
|
|
|
|
|
|
|
|
|
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:
|