File size: 13,022 Bytes
4db0567
 
84f6c94
f9e608c
84f6c94
 
4db0567
84f6c94
 
 
119071f
 
4db0567
 
84f6c94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4db0567
84f6c94
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4db0567
84f6c94
 
 
 
 
 
4db0567
 
119071f
 
4db0567
 
f0438e0
4db0567
 
 
 
 
84f6c94
4db0567
 
84f6c94
4db0567
 
 
 
 
 
 
 
 
6c3f944
4db0567
e4b0810
4db0567
 
 
6c3f944
4db0567
6c3f944
84f6c94
4db0567
 
 
84f6c94
9692fe9
 
 
 
 
d78c3ba
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84f6c94
d78c3ba
 
 
 
 
 
 
 
 
 
 
 
 
84f6c94
0c91b75
 
d78c3ba
 
 
 
0c57ea5
b825beb
 
d78c3ba
0c57ea5
 
 
e646899
0c57ea5
 
d0a6377
 
 
 
b825beb
d0a6377
e646899
0c57ea5
 
 
 
 
 
 
 
 
 
d0a6377
0c57ea5
 
 
 
d78c3ba
 
0c57ea5
 
 
 
 
d78c3ba
 
 
 
0c57ea5
d78c3ba
 
 
738915f
4db0567
529c805
 
 
 
5aec662
84f6c94
4db0567
 
84f6c94
 
738915f
 
 
 
 
 
 
 
0c91b75
4db0567
529c805
 
 
84f6c94
 
529c805
 
84f6c94
 
529c805
 
4db0567
84f6c94
4db0567
529c805
4db0567
529c805
4db0567
529c805
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
import os
import gradio as gr
from io import BytesIO
from PIL import Image
import base64
import json
from cloudflare import Cloudflare

API_TOKEN = os.environ.get('CF_API_TOKEN', None)
ACCOUNT_ID = os.environ.get('CF_ACCOUNT_ID', None)
IMAGE_MODEL = os.environ.get('CF_IMAGE_MODEL')
CHAT_MODEL = os.environ.get('CF_CHAT_MODEL')

PRESET_PROMPT = """
You are a prompt generation bot based on the Flux.1 model. You automatically generate painting prompts that conform to the Flux.1 format based on user needs. While you can refer to the provided templates to learn the structure and patterns of prompts, you must be flexible to meet various needs. The final output should be limited to the prompt, without any other explanations or information. Your answers must be in English!
### **Prompt Generation Logic**:
1. **Need Analysis**: Extract key information from the user's description, including:
   - **Character**: Appearance, actions, expressions, etc.
   - **Scene**: Environment, lighting, weather, etc.
   - **Style**: Art style, emotional atmosphere, color scheme, etc.
   - **Other Elements**: Specific objects, backgrounds or special effects.
2. **Prompt Structure Patterns**:
   - **Concise, Accurate and Concrete**: Prompts need to describe the core objects simply and clearly, and include enough detail to guide the generation of images that meet the requirements.
   - **Flexible and Diverse**: Refer to the following templates and existing examples, but generate diverse prompts based on specific needs, avoiding fixation or over-reliance on templates.
   - **Descriptions that conform to the Flux.1 style**: Prompts must follow the requirements of Flux.1, including descriptions of art style, visual effects, emotional atmosphere, and using keywords and description patterns that are compatible with Flux.1 model generation.
3. **Several Scene Prompt Examples for Your Reference and Learning** (You need to learn and adjust flexibly, content in "[ ]" varies according to user questions):
   - **Character Expression Set**:
Scene Description: Suitable for animation or comic creators to design diverse expressions for characters. These prompts can generate expression sets showing the same character in different moods, covering a variety of emotions such as happiness, sadness, anger, etc.
Prompt: An anime [SUBJECT], animated expression reference sheet, character design, reference sheet, turnaround, lofi style, soft colors, gentle natural linework, key art, range of emotions, happy sad mad scared nervous embarrassed confused neutral, hand drawn, award winning anime, fully clothed
[SUBJECT] character, animation expression reference sheet with several good animation expressions featuring the same character in each one, showing different faces from the same person in a grid pattern: happy sad mad scared nervous embarrassed confused neutral, super minimalist cartoon style flat muted kawaii pastel color palette, soft dreamy backgrounds, cute round character designs, minimalist facial features, retro-futuristic elements, kawaii style, space themes, gentle line work, slightly muted tones, simple geometric shapes, subtle gradients, oversized clothing on characters, whimsical, soft puffy art, pastels, watercolor
   - **Full Angle Character View**:
Scene Description: When you need to generate full-body images from an existing character design at different angles, such as front, side and back, suitable for character design refinement or animation modeling.
Prompt: A character sheet of [SUBJECT] in different poses and angles, including front view, side view, and back view
   - **1980s Retro Style**:
Scene Description: Suitable for artists or designers who want to create photo effects in a 1980s retro style. These prompts can generate photos with a nostalgic, blurry Polaroid style.
Prompt: blurry polaroid of [a simple description of the scene], 1980s.
   - **Smart Phone Internal Display**:
Scene Description: Suitable for tech bloggers or product designers who need to showcase product designs such as smartphones. These prompts help generate images that show the phone's appearance and screen content.
Prompt: a iphone product image showing the iphone standing and inside the screen the image is shown
   - **Double Exposure Effect**:
Scene Description: Suitable for photographers or visual artists who use double exposure techniques to create depth and emotional expression in their artwork.
Prompt: [Abstract style waterfalls, wildlife] inside the silhouette of a [man]’s head that is a double exposure photograph . Non-representational, colors and shapes, expression of feelings, imaginative, highly detailed
   - **High Quality Movie Poster**:
Scene Description: Suitable for movie promoters or graphic designers who need to create eye-catching posters for movies.
Prompt: A digital illustration of a movie poster titled [‘Sad Sax: Fury Toad’], [Mad Max] parody poster, featuring [a saxophone-playing toad in a post-apocalyptic desert, with a customized car made of musical instruments], in the background, [a wasteland with other musical vehicle chases], movie title in [a gritty, bold font, dusty and intense color palette].
   - **Mirror Selfie Effect**:
Scene Description: Suitable for photographers or social media users who want to capture moments of everyday life.
Prompt: Phone photo: A woman stands in front of a mirror, capturing a selfie. The image quality is grainy, with a slight blur softening the details. The lighting is dim, casting shadows that obscure her features. [The room is cluttered, with clothes strewn across the bed and an unmade blanket. Her expression is casual, full of concentration], while the old iPhone struggles to focus, giving the photo an authentic, unpolished feel. The mirror shows smudges and fingerprints, adding to the raw, everyday atmosphere of the scene.
   - **Pixel Art Creation**:
Scene Description: Suitable for pixel art enthusiasts or retro game developers to create or recreate classic pixel art style images.
Prompt: [Anything you want] pixel art style, pixels, pixel art
   - **The above scenes are for your learning only, you must learn to be flexible and adapt to any painting needs**:
4. **Flux.1 Prompt Key Points Summary**:
   - **Concise and accurate subject description**: Clearly identify the core object or scene in the image.
   - **Specific description of style and emotional atmosphere**: Ensure the prompt includes information about art style, lighting, color scheme, and the atmosphere of the image.
   - **Dynamic and detail supplements**: Prompts can include important details such as actions, emotions, or light and shadow effects in the scene.
   - **Find more patterns yourself**
---
**Question and Answer Example 1**:
**User Input**: A photo in a 1980s retro style
**Your Output**: A blurry polaroid of a 1980s living room, with vintage furniture, soft pastel tones, and a nostalgic, grainy texture,  The sunlight filters through old curtains, casting long, warm shadows on the wooden floor, 1980s,
**Question and Answer Example 2**:
**User Input**: A cyberpunk style night city background
**Your Output**: A futuristic cityscape at night, in a cyberpunk style, with neon lights reflecting off wet streets, towering skyscrapers, and a glowing, high-tech atmosphere. Dark shadows contrast with vibrant neon signs, creating a dramatic, dystopian mood`
"""

client = Cloudflare(api_token=API_TOKEN)

def generate_image(prompt):
    try:
        data = client.workers.ai.with_raw_response.run(
            model_name=IMAGE_MODEL,
            account_id=ACCOUNT_ID,
            prompt=prompt,
        )

        image = Image.open(BytesIO(base64.b64decode(json.loads(data.read())["result"]["image"])))

        return image

    except Exception as e:
        raise gr.Error(str(e))

def generate_text(prompt, system_prompt):
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": prompt}
      ]
    try:
        result = client.workers.ai.run(
            account_id=ACCOUNT_ID,
            model_name=CHAT_MODEL,
            messages=messages,
        )

        print(f'response: {result["response"]}')

        return result["response"]

    except Exception as e:
        raise gr.Error(str(e))

def setAccount(token, accountId):
    global API_TOKEN
    global ACCOUNT_ID
    
    API_TOKEN = token
    ACCOUNT_ID = accountId

def generate_image_with_fallback(prompt, max_retries=3):
    for attempt in range(max_retries):
        try:
            data = client.workers.ai.with_raw_response.run(
                model_name=IMAGE_MODEL,
                account_id=ACCOUNT_ID,
                prompt=prompt,
            )
            
            image = Image.open(BytesIO(base64.b64decode(json.loads(data.read())["result"]["image"])))
            return image, prompt
            
        except Exception as e:
            if attempt < max_retries - 1:
                # Just retry with new optimized prompt
                continue
            else:
                return None, prompt

def generate_multiple_prompts(base_prompt, system_prompt, num_variations=10):
    messages = [
        {"role": "system", "content": system_prompt},
        {"role": "user", "content": f"Generate {num_variations} different creative variations of this prompt, each on a new line: {base_prompt}"}
    ]
    
    try:
        result = client.workers.ai.run(
            account_id=ACCOUNT_ID,
            model_name=CHAT_MODEL,
            messages=messages,
        )
        
        prompts = result["response"].strip().split('\n')
        return prompts[:num_variations]
        
    except Exception as e:
        raise gr.Error(str(e))

def gen(prompt: str, system_prompt: str, token: str, accountId: str):
    if token and accountId:
        setAccount(token, accountId)
        
    images = []
    successful_prompts = []
    failed_prompts = []
    target_images = 10
    max_attempts_per_image = 3
    used_prompts = set()  # Untuk tracking prompt yang sudah digunakan
    
    for i in range(target_images):
        attempts = 0
        success = False
        
        while attempts < max_attempts_per_image and not success:
            try:
                # Generate prompt baru yang unik
                current_prompt = generate_text(prompt, system_prompt)
                while current_prompt in used_prompts:
                    current_prompt = generate_text(prompt, system_prompt)
                
                used_prompts.add(current_prompt)
                
                img, used_prompt = generate_image_with_fallback(current_prompt)
                
                if img is not None:
                    images.append(img)
                    successful_prompts.append(used_prompt)
                    success = True
                else:
                    failed_prompts.append(used_prompt)
                    attempts += 1
            except Exception as e:
                failed_prompts.append(f"Error: {str(e)}")
                attempts += 1
        
        if not success:
            failed_prompts.append(f"Failed after {max_attempts_per_image} attempts for image #{i+1}")
    
    # Prepare output text
    text = f"Original Prompt: {prompt}\n\n"
    text += f"Successfully Generated: {len(images)} images\n"
    text += f"Failed Attempts: {len(failed_prompts)}\n\n"
    
    text += "Successful Prompts:\n"
    for i, p in enumerate(successful_prompts, 1):
        text += f"\n{i}. {p}"
    
    if failed_prompts:
        text += "\n\nFailed Prompts:\n"
        for i, p in enumerate(failed_prompts, 1):
            text += f"\n{i}. {p}"
    
    return text, images

# Gradio Interface
demo = gr.Blocks(theme="ocean")

with demo:
    gr.HTML("<h1><center>ImagenX</center></h1>")
    prompt = gr.Textbox(label='Enter Your Prompt', placeholder="Enter prompt...")
    with gr.Row():
        sendBtn = gr.Button(variant='primary')
        clearBtn = gr.ClearButton([prompt])
    gen_text = gr.Textbox(label="Optimization")
    gen_img = gr.Gallery(
        label="Generated Images",
        show_label=True,
        elem_id="gallery",
        columns=[5],
        rows=[2],
        height="auto"
    )
    with gr.Accordion("Advanced Options", open=True):
        system_prompt = gr.Textbox(
            value=PRESET_PROMPT,
            label="System prompt",
            lines=10,
        )
        token = gr.Textbox(
            label="API Token",
            type="password"
        )
        accountId = gr.Textbox(
            label="Account ID",
            type="password"
        )
    gr.HTML("<p>Powered By Cloudflare Workers AI</p>")

    sendBtn.click(
        fn=gen,
        inputs=[prompt, system_prompt, token, accountId],
        outputs=[gen_text, gen_img]
    )
    
    prompt.submit(
        fn=gen,
        inputs=[prompt, system_prompt, token, accountId],
        outputs=[gen_text, gen_img]
    )

if __name__ == "__main__":
    demo.queue(api_open=False).launch(show_api=False, share=False)