Spaces:
vcollos
/
Runtime error

vcollos commited on
Commit
588fe35
·
verified ·
1 Parent(s): 605c374

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +266 -219
app.py CHANGED
@@ -26,10 +26,6 @@ supabase: Client = create_client(url, key)
26
  # Obtém token da Hugging Face
27
  hf_token = os.getenv("HF_TOKEN")
28
 
29
- # Configura as chaves de API da OpenAI e Google AI
30
- OPENAI_API_KEY = os.getenv("Openai", "")
31
- GOOGLE_AI_KEY = os.getenv("GoogleAi", "")
32
-
33
  # Inicializa o modelo base FLUX.1-dev
34
  base_model = "black-forest-labs/FLUX.1-dev"
35
  pipe = DiffusionPipeline.from_pretrained(
@@ -41,12 +37,12 @@ pipe = DiffusionPipeline.from_pretrained(
41
  # Move o modelo para GPU
42
  pipe.to("cuda")
43
 
44
- # Definição dos LoRA e Trigger Words - Melhoradas para caracterização mais forte
45
  lora_models = {
46
  "Paula": {
47
  "repo": "vcollos/Paula2",
48
  "weights": "Paula P.safetensors",
49
- "trigger_word": "woman with long blonde hair named Paula",
50
  "negative_word": "men, male, man, masculine features, dark hair",
51
  "character_desc": "a beautiful woman with long blonde hair, feminine features, soft facial features"
52
  },
@@ -55,7 +51,7 @@ lora_models = {
55
  "weights": "Vivi.safetensors",
56
  "trigger_word": "man with dark hair named Vivi",
57
  "negative_word": "women, female, woman, feminine features, blonde hair",
58
- "character_desc": "a handsome man with dark hair, masculine features, defined jawline"
59
  }
60
  }
61
 
@@ -89,188 +85,153 @@ def upload_image_to_supabase(image, filename):
89
  logger.error(f"❌ Erro no upload da imagem: {e}")
90
  return None
91
 
92
- def optimize_with_openai(text, character_option):
93
- """
94
- Otimiza o prompt usando a API da OpenAI.
95
- """
96
- try:
97
- # Determina o prompt de sistema com base na seleção de personagem
98
- if character_option == "Paula":
99
- system_prompt = f"""Você é um especialista em criar prompts para o modelo de imagem FLUX.1-dev.
100
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
101
- uma imagem de uma mulher loira chamada Paula.
102
-
103
- Descrição de Paula: {lora_models['Paula']['character_desc']}
104
-
105
- Seu prompt deve ser detalhado, claro e enfatizar características de uma mulher loira.
106
- Inclua aspectos como: cabelo loiro, características femininas, expressão facial.
107
-
108
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
109
- elif character_option == "Vivi":
110
- system_prompt = f"""Você é um especialista em criar prompts para o modelo de imagem FLUX.1-dev.
111
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
112
- uma imagem de um homem de cabelo escuro chamado Vivi.
113
-
114
- Descrição de Vivi: {lora_models['Vivi']['character_desc']}
115
-
116
- Seu prompt deve ser detalhado, claro e enfatizar características masculinas e cabelo escuro.
117
- Inclua aspectos como: cabelo escuro, características masculinas, expressão facial.
118
-
119
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
120
- else: # both
121
- system_prompt = f"""Você é um especialista em criar prompts para o modelo de imagem FLUX.1-dev.
122
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
123
- uma imagem de duas pessoas juntas: uma mulher loira chamada Paula e um homem de cabelo escuro chamado Vivi.
124
-
125
- Descrição de Paula: {lora_models['Paula']['character_desc']}
126
- Descrição de Vivi: {lora_models['Vivi']['character_desc']}
127
-
128
- Seu prompt deve ser detalhado, claro e deve enfatizar a presença dos DOIS personagens na mesma cena.
129
- IMPORTANTE: Mencione AMBOS os personagens de forma clara e distinta, enfatizando suas diferenças (homem/mulher, cabelo escuro/loiro).
130
-
131
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
132
-
133
- # Configuração do cabeçalho e corpo da requisição
134
- headers = {
135
- "Content-Type": "application/json",
136
- "Authorization": f"Bearer {OPENAI_API_KEY}"
137
- }
138
-
139
- data = {
140
- "model": "gpt-4",
141
- "messages": [
142
- {"role": "system", "content": system_prompt},
143
- {"role": "user", "content": text}
144
- ],
145
- "temperature": 0.7,
146
- "max_tokens": 300
147
- }
148
-
149
- # Faz a requisição para a API da OpenAI
150
- response = requests.post(
151
- "https://api.openai.com/v1/chat/completions",
152
- headers=headers,
153
- json=data
154
- )
155
-
156
- response.raise_for_status()
157
-
158
- # Extrai e retorna o prompt otimizado
159
- optimized_prompt = response.json()["choices"][0]["message"]["content"].strip()
160
- logger.info(f"✅ Prompt otimizado via OpenAI: {optimized_prompt}")
161
-
162
- return optimized_prompt
163
-
164
- except Exception as e:
165
- logger.error(f"❌ Erro ao otimizar prompt com OpenAI: {e}")
166
- return text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
- def optimize_with_google_ai(text, character_option):
169
  """
170
- Otimiza o prompt usando o Google AI API diretamente.
171
  """
172
- try:
173
- # Determina o prompt com base na seleção de personagem
174
- if character_option == "Paula":
175
- instruction = f"""Você é um especialista em criar prompts para modelos de imagem AI.
176
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
177
- uma imagem de uma mulher loira chamada Paula.
178
-
179
- Descrição de Paula: {lora_models['Paula']['character_desc']}
180
-
181
- Seu prompt deve ser detalhado, claro e enfatizar características de uma mulher loira.
182
- Inclua aspectos como: cabelo loiro, características femininas, expressão facial.
183
-
184
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
185
- elif character_option == "Vivi":
186
- instruction = f"""Você é um especialista em criar prompts para modelos de imagem AI.
187
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
188
- uma imagem de um homem de cabelo escuro chamado Vivi.
189
-
190
- Descrição de Vivi: {lora_models['Vivi']['character_desc']}
191
-
192
- Seu prompt deve ser detalhado, claro e enfatizar características masculinas e cabelo escuro.
193
- Inclua aspectos como: cabelo escuro, características masculinas, expressão facial.
194
-
195
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
196
- else: # both
197
- instruction = f"""Você é um especialista em criar prompts para modelos de imagem AI.
198
- Traduza e otimize este prompt em português para um prompt em inglês que irá gerar
199
- uma imagem de duas pessoas juntas: uma mulher loira chamada Paula e um homem de cabelo escuro chamado Vivi.
200
-
201
- Descrição de Paula: {lora_models['Paula']['character_desc']}
202
- Descrição de Vivi: {lora_models['Vivi']['character_desc']}
203
-
204
- Seu prompt deve ser detalhado, claro e deve enfatizar a presença dos DOIS personagens na mesma cena.
205
- IMPORTANTE: Mencione AMBOS os personagens de forma clara e distinta, enfatizando suas diferenças (homem/mulher, cabelo escuro/loiro).
206
-
207
- Responda APENAS com o prompt otimizado em inglês, sem explicações ou introduções."""
208
-
209
- # Prepara a requisição para a API do Google Gemini
210
- headers = {
211
- "Content-Type": "application/json"
212
- }
213
-
214
- url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key={GOOGLE_AI_KEY}"
215
-
216
- data = {
217
- "contents": [
218
- {
219
- "parts": [
220
- {
221
- "text": f"{instruction}\n\nPrompt original: {text}"
222
- }
223
- ]
224
- }
225
- ],
226
- "generationConfig": {
227
- "temperature": 0.7,
228
- "topK": 32,
229
- "topP": 1,
230
- "maxOutputTokens": 300
231
- }
232
- }
233
-
234
- # Faz a requisição para o Google AI
235
- response = requests.post(url, headers=headers, json=data)
236
- response.raise_for_status()
237
 
238
- # Extrai a resposta
239
- text_response = response.json()["candidates"][0]["content"]["parts"][0]["text"]
240
- logger.info(f" Prompt otimizado via Google AI: {text_response}")
241
 
242
- return text_response.strip()
 
 
243
 
244
- except Exception as e:
245
- logger.error(f"❌ Erro ao otimizar prompt com Google AI: {e}")
246
- # Tenta o OpenAI como fallback
247
- logger.info("🔄 Tentando OpenAI como fallback...")
248
- return optimize_with_openai(text, character_option)
249
 
250
  @spaces.GPU(duration=80)
251
- def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora_option, lora_scale_1, lora_scale_2, lora_balance, ai_option, use_negative_prompt, progress=gr.Progress(track_tqdm=True)):
 
 
 
 
 
252
  if randomize_seed:
253
  seed = random.randint(0, MAX_SEED)
254
  generator = torch.Generator(device="cuda").manual_seed(seed)
255
 
256
  original_prompt = prompt # Guarda o prompt original para metadados
257
 
258
- # Determina qual personagem está sendo usado para a otimização
259
- character_option = "Paula" if lora_option == "Paula" else "Vivi" if lora_option == "Vivi" else "both"
260
-
261
- # Processa o prompt de acordo com a opção selecionada
262
- processed_prompt = prompt # Valor padrão
263
-
264
- if ai_option == "OpenAI":
265
- processed_prompt = optimize_with_openai(prompt, character_option)
266
- elif ai_option == "Google AI":
267
- processed_prompt = optimize_with_google_ai(prompt, character_option)
268
- elif ai_option == "Nenhum":
269
- # Mantém o prompt original, sem processamento
270
- processed_prompt = prompt
271
-
272
- # Atualiza o prompt com o texto processado
273
- prompt = processed_prompt
274
 
275
  # Trunca o prompt para 77 tokens para evitar erro do CLIP
276
  prompt_tokens = prompt.split()[:77]
@@ -281,12 +242,22 @@ def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora
281
  adapter_weights = []
282
  negative_prompt = ""
283
 
 
 
 
 
 
 
 
 
 
 
284
  # Modificado para melhorar a caracterização de personagens
285
  if lora_option == "Paula":
286
  selected_loras.append("Paula")
287
  adapter_weights.append(lora_scale_1)
288
  # Adiciona mais ênfase no personagem e suas características
289
- prompt = f"{lora_models['Paula']['trigger_word']}, {lora_models['Paula']['character_desc']}, {prompt}"
290
  if use_negative_prompt:
291
  negative_prompt = lora_models['Paula']['negative_word']
292
 
@@ -294,7 +265,7 @@ def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora
294
  selected_loras.append("Vivi")
295
  adapter_weights.append(lora_scale_2)
296
  # Adiciona mais ênfase no personagem e suas características
297
- prompt = f"{lora_models['Vivi']['trigger_word']}, {lora_models['Vivi']['character_desc']}, {prompt}"
298
  if use_negative_prompt:
299
  negative_prompt = lora_models['Vivi']['negative_word']
300
 
@@ -307,7 +278,7 @@ def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora
307
  adapter_weights = [p_weight, v_weight]
308
 
309
  # Quando usando ambos, adiciona descrições mais explícitas para cada personagem
310
- prompt = f"{lora_models['Paula']['trigger_word']} and {lora_models['Vivi']['trigger_word']} together, side by side, a blonde woman and a dark-haired man, {prompt}"
311
 
312
  pipe.set_adapters(selected_loras, adapter_weights)
313
 
@@ -346,10 +317,10 @@ def run_lora(prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora
346
  try:
347
  response = supabase.table("images").insert({
348
  "prompt": original_prompt, # Salva o prompt original
349
- "processed_prompt": processed_prompt, # Salva o prompt processado pela IA
350
  "full_prompt": prompt, # Salva o prompt completo com trigger words
351
  "negative_prompt": negative_prompt,
352
- "ai_option": ai_option,
353
  "cfg_scale": cfg_scale,
354
  "steps": steps,
355
  "seed": seed,
@@ -378,61 +349,137 @@ with gr.Blocks(theme=gr_theme) as app:
378
 
379
  with gr.Row():
380
  with gr.Column(scale=2):
381
- prompt = gr.TextArea(label="Prompt em Português", placeholder="Digite um prompt em português descrevendo o que você quer", lines=3)
382
- generate_button = gr.Button("Gerar")
 
 
 
 
383
 
384
  with gr.Accordion("Configurações Básicas", open=True):
385
- cfg_scale = gr.Slider(label="CFG Scale", minimum=1, maximum=20, step=0.5, value=7.5)
386
- steps = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=30)
 
 
 
 
 
 
 
 
387
  width = gr.Slider(label="Width", minimum=256, maximum=1024, step=64, value=768)
388
  height = gr.Slider(label="Height", minimum=256, maximum=1024, step=64, value=1024)
389
- randomize_seed = gr.Checkbox(False, label="Randomize seed")
390
  seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=556215326)
391
 
392
  with gr.Accordion("Configurações de LoRA", open=True):
393
- lora_option = gr.Radio(["Nenhum", "Paula", "Vivi", "Ambos"], label="Escolha o LoRA", value="Ambos")
394
- lora_scale_1 = gr.Slider(label="LoRA Scale (Paula)", minimum=0, maximum=1, step=0.01, value=0.85)
395
- lora_scale_2 = gr.Slider(label="LoRA Scale (Vivi)", minimum=0, maximum=1, step=0.01, value=0.85)
396
- lora_balance = gr.Slider(label="Balanço entre personagens", minimum=0.5, maximum=1.5, step=0.05, value=1.0,
397
- info="Valores acima de 1.0 favorecem Paula, abaixo de 1.0 favorecem Vivi")
398
- use_negative_prompt = gr.Checkbox(True, label="Usar negative prompt", info="Ajuda a evitar mistura de características")
399
-
400
- with gr.Accordion("Processamento de Prompt", open=True):
401
- ai_option = gr.Radio(
402
- ["Nenhum", "OpenAI", "Google AI"],
403
- label="Método de Otimização",
404
- value="Google AI"
405
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
 
407
  with gr.Column(scale=2):
408
- result = gr.Image(label="Generated Image")
409
- final_prompt = gr.Textbox(label="Prompt Final (usado para gerar a imagem)", lines=3)
410
- gr.Markdown("""
411
- ### Como melhorar a identidade de cada personagem:
412
 
413
- 1. **Para apenas Paula (mulher loira)**:
414
- - Use CFG Scale mais alto (7-9)
415
- - LoRA Scale para Paula em 0.85-0.95
416
- - Mantenha o "Usar negative prompt" ativado
417
- - Mencione explicitamente "mulher loira" no prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
418
 
419
- 2. **Para apenas Vivi (homem de cabelo escuro)**:
420
- - Use CFG Scale mais alto (7-9)
421
- - LoRA Scale para Vivi em 0.85-0.95
422
- - Mantenha o "Usar negative prompt" ativado
423
- - Mencione explicitamente "homem de cabelo escuro" no prompt
 
 
 
 
 
 
 
 
 
 
424
 
425
- 3. **Para ambos juntos**:
426
- - Use o modo "Ambos" com valores iguais para os dois LoRAs
427
- - Descreva claramente uma "mulher loira e um homem de cabelo escuro" no prompt
428
- - Use uma seed que funcione bem (teste várias)
429
- - Um CFG Scale entre 7-8 costuma dar bons resultados
430
- - Especifique que eles estão "lado a lado" ou "juntos na mesma cena"
431
- """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
 
433
  generate_button.click(
434
  run_lora,
435
- inputs=[prompt, cfg_scale, steps, randomize_seed, seed, width, height, lora_option, lora_scale_1, lora_scale_2, lora_balance, ai_option, use_negative_prompt],
 
 
 
 
436
  outputs=[result, seed, final_prompt],
437
  )
438
 
 
26
  # Obtém token da Hugging Face
27
  hf_token = os.getenv("HF_TOKEN")
28
 
 
 
 
 
29
  # Inicializa o modelo base FLUX.1-dev
30
  base_model = "black-forest-labs/FLUX.1-dev"
31
  pipe = DiffusionPipeline.from_pretrained(
 
37
  # Move o modelo para GPU
38
  pipe.to("cuda")
39
 
40
+ # Definição dos LoRA e Trigger Words - Mais eficazes para gerar os personagens corretamente
41
  lora_models = {
42
  "Paula": {
43
  "repo": "vcollos/Paula2",
44
  "weights": "Paula P.safetensors",
45
+ "trigger_word": "woman with long blonde hair named Paula",
46
  "negative_word": "men, male, man, masculine features, dark hair",
47
  "character_desc": "a beautiful woman with long blonde hair, feminine features, soft facial features"
48
  },
 
51
  "weights": "Vivi.safetensors",
52
  "trigger_word": "man with dark hair named Vivi",
53
  "negative_word": "women, female, woman, feminine features, blonde hair",
54
+ "character_desc": "a handsome man with dark hair, masculine features, defined jawline"
55
  }
56
  }
57
 
 
85
  logger.error(f"❌ Erro no upload da imagem: {e}")
86
  return None
87
 
88
+ # Dicionário simples de tradução português-inglês para palavras comuns
89
+ translations = {
90
+ "homem": "man",
91
+ "mulher": "woman",
92
+ "juntos": "together",
93
+ "e": "and",
94
+ "com": "with",
95
+ "dois": "two",
96
+ "duas": "two",
97
+ "pessoas": "people",
98
+ "pessoa": "person",
99
+ "sentado": "sitting",
100
+ "sentada": "sitting",
101
+ "em pé": "standing",
102
+ "conversa": "conversation",
103
+ "conversando": "talking",
104
+ "falando": "talking",
105
+ "praia": "beach",
106
+ "jardim": "garden",
107
+ "casa": "house",
108
+ "cidade": "city",
109
+ "parque": "park",
110
+ "floresta": "forest",
111
+ "montanha": "mountain",
112
+ "rio": "river",
113
+ "lago": "lake",
114
+ "mar": "sea",
115
+ "oceano": "ocean",
116
+ "céu": "sky",
117
+ "nuvem": "cloud",
118
+ "sol": "sun",
119
+ "lua": "moon",
120
+ "estrela": "star",
121
+ "dia": "day",
122
+ "noite": "night",
123
+ "manhã": "morning",
124
+ "tarde": "afternoon",
125
+ "amigo": "friend",
126
+ "amiga": "friend",
127
+ "casal": "couple",
128
+ "família": "family",
129
+ "irmão": "brother",
130
+ "irmã": "sister",
131
+ "pai": "father",
132
+ "mãe": "mother",
133
+ "filho": "son",
134
+ "filha": "daughter",
135
+ "avô": "grandfather",
136
+ "avó": "grandmother",
137
+ "tio": "uncle",
138
+ "tia": "aunt",
139
+ "primo": "cousin",
140
+ "prima": "cousin",
141
+ "namorado": "boyfriend",
142
+ "namorada": "girlfriend",
143
+ "marido": "husband",
144
+ "esposa": "wife",
145
+ "amor": "love",
146
+ "feliz": "happy",
147
+ "triste": "sad",
148
+ "bravo": "angry",
149
+ "assustado": "scared",
150
+ "surpreso": "surprised",
151
+ "cansado": "tired",
152
+ "entediado": "bored",
153
+ "excitado": "excited",
154
+ "confuso": "confused",
155
+ # Adiciona mais termos de ambientes/ações/situações
156
+ "café": "coffee shop",
157
+ "restaurante": "restaurant",
158
+ "cinema": "movie theater",
159
+ "shopping": "mall",
160
+ "biblioteca": "library",
161
+ "escritório": "office",
162
+ "hotel": "hotel",
163
+ "aeroporto": "airport",
164
+ "estação": "station",
165
+ "hospital": "hospital",
166
+ "escola": "school",
167
+ "universidade": "university",
168
+ "igreja": "church",
169
+ "teatro": "theater",
170
+ "museu": "museum",
171
+ "bar": "bar",
172
+ "festa": "party",
173
+ "casamento": "wedding",
174
+ "aniversário": "birthday",
175
+ "caminhando": "walking",
176
+ "correndo": "running",
177
+ "dançando": "dancing",
178
+ "cantando": "singing",
179
+ "tocando": "playing",
180
+ "dirigindo": "driving",
181
+ "nadando": "swimming",
182
+ "assistindo": "watching",
183
+ "lendo": "reading",
184
+ "escrevendo": "writing",
185
+ "cozinhando": "cooking",
186
+ "comendo": "eating",
187
+ "bebendo": "drinking",
188
+ "dormindo": "sleeping",
189
+ "trabalhando": "working",
190
+ "estudando": "studying",
191
+ "fotografando": "photographing",
192
+ "pintando": "painting",
193
+ "desenhando": "drawing"
194
+ }
195
 
196
+ def simple_translate(text):
197
  """
198
+ Função simples para traduzir texto para inglês usando o dicionário de traduções.
199
  """
200
+ translated_text = text.lower()
201
+
202
+ for pt, en in translations.items():
203
+ # Use word boundary to avoid partial matches
204
+ translated_text = translated_text.replace(f" {pt} ", f" {en} ")
205
+ translated_text = translated_text.replace(f" {pt},", f" {en},")
206
+ translated_text = translated_text.replace(f" {pt}.", f" {en}.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
 
208
+ # Check for word at beginning of string
209
+ if translated_text.startswith(f"{pt} "):
210
+ translated_text = f"{en} " + translated_text[len(pt)+1:]
211
 
212
+ # Check for word at end of string
213
+ if translated_text.endswith(f" {pt}"):
214
+ translated_text = translated_text[:-len(pt)-1] + f" {en}"
215
 
216
+ logger.info(f"Texto traduzido: {translated_text}")
217
+ return translated_text
 
 
 
218
 
219
  @spaces.GPU(duration=80)
220
+ def run_lora(
221
+ prompt, cfg_scale, steps, randomize_seed, seed, width, height,
222
+ lora_option, lora_scale_1, lora_scale_2, lora_balance,
223
+ translate_prompt, use_negative_prompt, quality_preset,
224
+ progress=gr.Progress(track_tqdm=True)
225
+ ):
226
  if randomize_seed:
227
  seed = random.randint(0, MAX_SEED)
228
  generator = torch.Generator(device="cuda").manual_seed(seed)
229
 
230
  original_prompt = prompt # Guarda o prompt original para metadados
231
 
232
+ # Traduz o prompt se a opção estiver ativada
233
+ if translate_prompt:
234
+ prompt = simple_translate(prompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  # Trunca o prompt para 77 tokens para evitar erro do CLIP
237
  prompt_tokens = prompt.split()[:77]
 
242
  adapter_weights = []
243
  negative_prompt = ""
244
 
245
+ # Aplica preset de qualidade
246
+ if quality_preset == "Alta Qualidade":
247
+ quality_terms = ", professional photography, detailed, high quality, 8k, masterpiece, best quality"
248
+ elif quality_preset == "Artístico":
249
+ quality_terms = ", artistic, cinematic lighting, dramatic, professional, detailed"
250
+ elif quality_preset == "Realista":
251
+ quality_terms = ", photorealistic, detailed skin, detailed face, high detail, realistic"
252
+ else: # Nenhum
253
+ quality_terms = ""
254
+
255
  # Modificado para melhorar a caracterização de personagens
256
  if lora_option == "Paula":
257
  selected_loras.append("Paula")
258
  adapter_weights.append(lora_scale_1)
259
  # Adiciona mais ênfase no personagem e suas características
260
+ prompt = f"{lora_models['Paula']['trigger_word']}, {lora_models['Paula']['character_desc']}, {prompt}{quality_terms}"
261
  if use_negative_prompt:
262
  negative_prompt = lora_models['Paula']['negative_word']
263
 
 
265
  selected_loras.append("Vivi")
266
  adapter_weights.append(lora_scale_2)
267
  # Adiciona mais ênfase no personagem e suas características
268
+ prompt = f"{lora_models['Vivi']['trigger_word']}, {lora_models['Vivi']['character_desc']}, {prompt}{quality_terms}"
269
  if use_negative_prompt:
270
  negative_prompt = lora_models['Vivi']['negative_word']
271
 
 
278
  adapter_weights = [p_weight, v_weight]
279
 
280
  # Quando usando ambos, adiciona descrições mais explícitas para cada personagem
281
+ prompt = f"{lora_models['Paula']['trigger_word']} and {lora_models['Vivi']['trigger_word']} together, side by side, a blonde woman and a dark-haired man, {prompt}{quality_terms}"
282
 
283
  pipe.set_adapters(selected_loras, adapter_weights)
284
 
 
317
  try:
318
  response = supabase.table("images").insert({
319
  "prompt": original_prompt, # Salva o prompt original
320
+ "translated_prompt": prompt if translate_prompt else original_prompt,
321
  "full_prompt": prompt, # Salva o prompt completo com trigger words
322
  "negative_prompt": negative_prompt,
323
+ "quality_preset": quality_preset,
324
  "cfg_scale": cfg_scale,
325
  "steps": steps,
326
  "seed": seed,
 
349
 
350
  with gr.Row():
351
  with gr.Column(scale=2):
352
+ prompt = gr.TextArea(
353
+ label="Prompt",
354
+ placeholder="Digite um prompt descrevendo o ambiente e ações (pode ser em português)",
355
+ lines=3
356
+ )
357
+ generate_button = gr.Button("Gerar Imagem", variant="primary")
358
 
359
  with gr.Accordion("Configurações Básicas", open=True):
360
+ translate_prompt = gr.Checkbox(True, label="Traduzir prompt do português para inglês")
361
+ quality_preset = gr.Radio(
362
+ ["Nenhum", "Alta Qualidade", "Artístico", "Realista"],
363
+ label="Preset de Qualidade",
364
+ value="Alta Qualidade"
365
+ )
366
+ cfg_scale = gr.Slider(label="CFG Scale", minimum=1, maximum=20, step=0.5, value=8.0)
367
+ steps = gr.Slider(label="Steps", minimum=1, maximum=100, step=1, value=35)
368
+
369
+ with gr.Accordion("Tamanho e Seed", open=False):
370
  width = gr.Slider(label="Width", minimum=256, maximum=1024, step=64, value=768)
371
  height = gr.Slider(label="Height", minimum=256, maximum=1024, step=64, value=1024)
372
+ randomize_seed = gr.Checkbox(True, label="Randomize seed")
373
  seed = gr.Slider(label="Seed", minimum=0, maximum=MAX_SEED, step=1, value=556215326)
374
 
375
  with gr.Accordion("Configurações de LoRA", open=True):
376
+ lora_option = gr.Radio(
377
+ ["Paula", "Vivi", "Ambos"],
378
+ label="Escolha o LoRA",
379
+ value="Ambos"
380
+ )
381
+ use_negative_prompt = gr.Checkbox(
382
+ True,
383
+ label="Usar negative prompt",
384
+ info="Ajuda a evitar mistura de características"
 
 
 
385
  )
386
+ with gr.Group(visible=True) as lora_controls:
387
+ lora_scale_1 = gr.Slider(
388
+ label="Intensidade do LoRA (Paula)",
389
+ minimum=0, maximum=1, step=0.05, value=0.85
390
+ )
391
+ lora_scale_2 = gr.Slider(
392
+ label="Intensidade do LoRA (Vivi)",
393
+ minimum=0, maximum=1, step=0.05, value=0.85
394
+ )
395
+ lora_balance = gr.Slider(
396
+ label="Balanço entre personagens",
397
+ minimum=0.5, maximum=1.5, step=0.05, value=1.0,
398
+ info="Valores acima de 1.0 favorecem Paula, abaixo de 1.0 favorecem Vivi"
399
+ )
400
 
401
  with gr.Column(scale=2):
402
+ result = gr.Image(label="Imagem Gerada", type="pil")
403
+ final_prompt = gr.Textbox(label="Prompt Final", lines=3)
 
 
404
 
405
+ with gr.Accordion("Instruções", open=True):
406
+ gr.Markdown("""
407
+ ### Como escrever prompts eficientes:
408
+
409
+ **O que colocar no prompt:**
410
+ - **Ambiente/cenário**: "em uma praia", "em um café", "em uma floresta"
411
+ - **Ações/atividades**: "conversando", "caminhando", "segurando mãos"
412
+ - **Roupas/acessórios**: "vestido azul", "terno preto", "chapéu de palha"
413
+ - **Iluminação/hora do dia**: "pôr do sol", "luz noturna", "iluminação suave"
414
+
415
+ **O que NÃO precisa incluir:**
416
+ - Não mencione "Paula" ou "Vivi" - o sistema já adiciona isso
417
+ - Não mencione "mulher loira" ou "homem moreno" - isso já está incluído
418
+
419
+ **Exemplos de bons prompts:**
420
+ - "Em um café à beira-mar, conversando e rindo, pôr do sol"
421
+ - "Caminhando em um parque de outono, roupas elegantes"
422
+ - "Em uma festa, dançando juntos, luzes coloridas"
423
+ """)
424
 
425
+ with gr.Accordion("Dicas para melhores resultados", open=False):
426
+ gr.Markdown("""
427
+ ### Para um personagem só:
428
+ - Mantenha o CFG Scale alto (7-9)
429
+ - Intensidade do LoRA em 0.85-0.95
430
+ - Deixe "Usar negative prompt" ativado
431
+ - Use o preset "Realista" para fotos mais realistas
432
+
433
+ ### Para ambos personagens juntos:
434
+ - Use valores iguais para intensidade dos LoRAs
435
+ - Mencione explicitamente que estão "juntos" ou "lado a lado"
436
+ - Um CFG Scale entre 7-10 geralmente funciona melhor
437
+ - Teste diferentes seeds até encontrar uma que funcione bem
438
+ - O preset "Alta Qualidade" geralmente funciona melhor
439
+ """)
440
 
441
+ # Mostra exemplos de seeds que funcionam bem
442
+ with gr.Accordion("Seeds que funcionam bem", open=False):
443
+ gr.Markdown("""
444
+ ### Seeds testadas que geram bons resultados:
445
+
446
+ **Para Paula:**
447
+ - 42689753: Paula em vestido azul
448
+ - 78942561: Paula em ambiente externo
449
+ - 15983264: Close-up de Paula sorrindo
450
+
451
+ **Para Vivi:**
452
+ - 36798245: Vivi em traje formal
453
+ - 65123987: Vivi em ambiente urbano
454
+ - 93254168: Close-up de Vivi
455
+
456
+ **Para ambos juntos:**
457
+ - 25874136: Casal em um café
458
+ - 78963214: Passeando em um parque
459
+ - 46125893: Em um restaurante à noite
460
+ """)
461
+
462
+ # Define a lógica para mostrar/esconder controles baseado na seleção
463
+ def update_lora_controls(option):
464
+ return {
465
+ lora_scale_1: gr.update(visible=option in ["Paula", "Ambos"]),
466
+ lora_scale_2: gr.update(visible=option in ["Vivi", "Ambos"]),
467
+ lora_balance: gr.update(visible=option == "Ambos")
468
+ }
469
+
470
+ lora_option.change(
471
+ update_lora_controls,
472
+ inputs=[lora_option],
473
+ outputs=[lora_scale_1, lora_scale_2, lora_balance]
474
+ )
475
 
476
  generate_button.click(
477
  run_lora,
478
+ inputs=[
479
+ prompt, cfg_scale, steps, randomize_seed, seed, width, height,
480
+ lora_option, lora_scale_1, lora_scale_2, lora_balance,
481
+ translate_prompt, use_negative_prompt, quality_preset
482
+ ],
483
  outputs=[result, seed, final_prompt],
484
  )
485