byte-vortex commited on
Commit
bd160cc
Β·
verified Β·
1 Parent(s): a74fdb7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -35
app.py CHANGED
@@ -17,13 +17,35 @@ DEFAULT_SIZE = 512
17
  MAX_SEED = np.iinfo(np.int32).max
18
 
19
  # -----------------------------
20
- # 1. System & Model Setup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  # -----------------------------
22
 
23
  class MockPipe:
24
  """A dummy pipeline for testing without a GPU."""
25
  def __call__(self, *args, **kwargs):
26
- time.sleep(1.5) # Simulate "thinking" time
27
  color = kwargs.get('color_hint', 'red')
28
  return type('obj', (object,), {'images': [Image.new('RGB', (512, 512), color=color)]})
29
 
@@ -42,28 +64,12 @@ try:
42
  requires_safety_checker=False
43
  ).to(device)
44
  else:
45
- # Fallback for CPU
46
  pipe = MockPipe()
47
  print("⚠️ GPU not found. Using MockPipe for UI demonstration.")
48
  except Exception as e:
49
  print(f"⚠️ Model failed to load. Using MockPipe. Error: {e}")
50
  pipe = MockPipe()
51
 
52
- # -----------------------------
53
- # 2. Configuration & Logic
54
- # -----------------------------
55
- PANEL_V1_PRESETS = {
56
- "Oil Painting 🎨": {"prompt": "Oil painting, heavy impasto, visible brushstrokes, masterpiece", "neg": "photorealistic, smooth, digital", "str": 0.80},
57
- "Ink Illustration βœ’οΈ": {"prompt": "Ink and watercolor sketch, loose lines, artistic, intricate details", "neg": "3d render, solid colors", "str": 0.70},
58
- "Noir Photography πŸ“Έ": {"prompt": "High contrast black and white photography, film grain, dramatic shadows", "neg": "color, soft, painting", "str": 0.65},
59
- }
60
-
61
- PANEL_V2_PRESETS = {
62
- "Cyberpunk City πŸŒ†": {"prompt": "Cyberpunk atmosphere, neon lights, rain, volumetric fog, futuristic", "neg": "daylight, rustic, vintage", "str": 0.55},
63
- "Scenic Anime πŸ—Ύ": {"prompt": "High quality anime background art, hand-painted style, cumulus clouds, rolling hills, vibrant nature", "neg": "dark, gritty, horror, realism, sketch", "str": 0.60},
64
- "Retro Vaporwave πŸ“Ό": {"prompt": "Vaporwave aesthetic, pink and purple gradient lighting, VHS glitch effect", "neg": "high definition, neutral colors", "str": 0.50},
65
- }
66
-
67
  class AriaAgent:
68
  def __init__(self, pipe, device):
69
  self.pipe = pipe
@@ -71,38 +77,40 @@ class AriaAgent:
71
 
72
  def generate_reasoning(self, phase, tool_name, strength, user_intent):
73
  """Generates 'Chain of Thought' internal monologue text."""
 
 
 
 
74
  if phase == "analysis":
75
  return (
76
  f"πŸ’­ THOUGHT: Analyzing input signal data...\n"
77
- f" > Observation: User provided semantic intent: '{user_intent}'\n"
78
  f" > Assessment: Input image requires stylistic abstraction.\n"
79
- f" > Strategy: I will split the task into Structure (Step 1) and Atmosphere (Step 2)."
80
  )
81
  elif phase == "step1":
82
  return (
83
  f"πŸ’­ THOUGHT: Executing Foundation Layer.\n"
84
  f" > Selection: Tool '{tool_name}' chosen to break photorealism.\n"
85
  f" > Parameter Reasoning: Setting denoising strength to {strength:.2f}.\n"
86
- f" - Rationale: A high value is needed to overwrite original textures while keeping composition.\n"
87
  f" > Action: Injecting latent noise vectors..."
88
  )
89
  elif phase == "step2":
90
  return (
91
  f"πŸ’­ THOUGHT: Refining Atmospheric Context.\n"
92
  f" > Selection: Tool '{tool_name}' chosen for lighting and mood.\n"
93
- f" > Parameter Reasoning: Reducing strength to {strength:.2f} to preserve the Step 1 strokes.\n"
94
- f" > Optimization: Aligning vector guidance with '{user_intent}'.\n"
95
  f" > Action: Final render pass initiating."
96
  )
97
  return ""
98
 
99
  def generate(self, image, prompt, neg, strength, steps, guide, seed):
100
- # Mock generation logic for 'MockPipe'
101
  if isinstance(self.pipe, MockPipe):
102
  color = '#8b5cf6' if "Style" in prompt else '#10b981'
103
  return self.pipe(color_hint=color).images[0]
104
 
105
- # Real generation logic
106
  with torch.inference_mode():
107
  image = image.resize((DEFAULT_SIZE, DEFAULT_SIZE))
108
  gen = torch.Generator(device=self.device).manual_seed(seed)
@@ -126,19 +134,22 @@ def run_ui_stream(
126
 
127
  if init_img is None:
128
  raise gr.Error("Please upload an input image first.")
129
-
130
  # 1. Initialization
131
  if rnd: seed = random.randint(0, MAX_SEED)
132
  gallery_state.append((init_img, "1. Input Signal"))
133
 
134
  # --- COT: Analysis Phase ---
135
- analysis_thought = agent.generate_reasoning("analysis", "", 0, user_p if user_p else "General Transformation")
136
  logs.append(analysis_thought)
137
  yield "\n\n".join(logs), gallery_state, seed, "πŸ€” ANALYZING"
138
- time.sleep(0.8) # Pause to let user read the "thought"
139
 
140
  # --- COT: Step 1 Planning ---
 
 
141
  p1 = PANEL_V1_PRESETS[v1_key]
 
142
  final_str_1 = min(1.0, p1['str'] * strength_mult)
143
 
144
  step1_thought = agent.generate_reasoning("step1", v1_key, final_str_1, user_p)
@@ -153,7 +164,9 @@ def run_ui_stream(
153
  yield "\n\n".join(logs), gallery_state, seed, "πŸ‘€ OBSERVING"
154
 
155
  # --- COT: Step 2 Planning ---
 
156
  p2 = PANEL_V2_PRESETS[v2_key]
 
157
  step2_thought = agent.generate_reasoning("step2", v2_key, p2['str'], user_p)
158
  logs.append(step2_thought)
159
  yield "\n\n".join(logs), gallery_state, seed, "🌫️ ATMOSPHERE"
@@ -183,10 +196,10 @@ h1 {
183
  text-shadow: 0 0 10px rgba(56, 189, 248, 0.5);
184
  }
185
 
186
- /* FIXED: Subtitle is now bright Amber for high contrast */
187
  .subtitle {
188
  font-family: 'Space Mono', monospace;
189
- color: #fbbf24; /* Amber-400 */
190
  font-weight: bold;
191
  font-size: 1.0rem;
192
  letter-spacing: 1px;
@@ -209,10 +222,9 @@ h1 {
209
  }
210
  #run-btn:hover { transform: scale(1.02); box-shadow: 0 0 25px rgba(139, 92, 246, 0.7); }
211
 
212
- /* Styled to look like a terminal code block */
213
  #log-output-box textarea {
214
  background-color: #0d1117 !important;
215
- color: #4ade80 !important; /* Matrix Green text */
216
  font-family: 'Space Mono', monospace !important;
217
  font-size: 0.85rem !important;
218
  border: 1px solid #30363d !important;
@@ -245,7 +257,6 @@ with gr.Blocks(theme=theme, css=hackathon_css, title="A.R.I.A. Agent") as demo:
245
  with gr.Row(elem_classes="header-row"):
246
  with gr.Column(scale=6):
247
  gr.Markdown(f"# 🧬 {APP_TITLE}")
248
- # Subtitle class applied here
249
  gr.HTML(f"<span class='subtitle'>{APP_SUBTITLE}</span>")
250
  with gr.Column(scale=2):
251
  status_display = gr.Textbox(value="🟒 SYSTEM READY", label="Agent Status", interactive=False, elem_id="status-bar")
@@ -263,9 +274,22 @@ with gr.Blocks(theme=theme, css=hackathon_css, title="A.R.I.A. Agent") as demo:
263
  gr.Markdown("### πŸ•ΉοΈ 2. Parameters")
264
  user_prompt = gr.Textbox(label="Creative Guidance", placeholder="E.g. 'A futuristic city at night'...", lines=2)
265
 
 
266
  with gr.Row():
267
- v1_select = gr.Dropdown(label="Tool A: Foundation", choices=list(PANEL_V1_PRESETS.keys()), value="Oil Painting 🎨")
268
- v2_select = gr.Dropdown(label="Tool B: Atmosphere", choices=list(PANEL_V2_PRESETS.keys()), value="Scenic Anime πŸ—Ύ")
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
  strength_mult_slide = gr.Slider(label="Concept Divergence", minimum=0.2, maximum=1.0, value=0.9, step=0.05)
271
 
 
17
  MAX_SEED = np.iinfo(np.int32).max
18
 
19
  # -----------------------------
20
+ # 1. Configuration & Presets
21
+ # -----------------------------
22
+
23
+ # Defining these as lists first ensures consistency between UI and Logic
24
+ PANEL_V1_PRESETS = {
25
+ "Oil Painting 🎨": {"prompt": "Oil painting, heavy impasto, visible brushstrokes, masterpiece", "neg": "photorealistic, smooth, digital", "str": 0.80},
26
+ "Ink Illustration βœ’οΈ": {"prompt": "Ink and watercolor sketch, loose lines, artistic, intricate details", "neg": "3d render, solid colors", "str": 0.70},
27
+ "Noir Photography πŸ“Έ": {"prompt": "High contrast black and white photography, film grain, dramatic shadows", "neg": "color, soft, painting", "str": 0.65},
28
+ "Watercolor πŸ’§": {"prompt": "Soft watercolor painting, bleeding edges, wet on wet, paper texture", "neg": "harsh lines, digital, opaque", "str": 0.75},
29
+ }
30
+
31
+ PANEL_V2_PRESETS = {
32
+ "Scenic Anime πŸ—Ύ": {"prompt": "High quality anime background art, hand-painted style, cumulus clouds, rolling hills, vibrant nature", "neg": "dark, gritty, horror, realism, sketch", "str": 0.60},
33
+ "Cyberpunk City πŸŒ†": {"prompt": "Cyberpunk atmosphere, neon lights, rain, volumetric fog, futuristic", "neg": "daylight, rustic, vintage", "str": 0.55},
34
+ "Retro Vaporwave πŸ“Ό": {"prompt": "Vaporwave aesthetic, pink and purple gradient lighting, VHS glitch effect", "neg": "high definition, neutral colors", "str": 0.50},
35
+ "Ethereal Fantasy ✨": {"prompt": "Dreamy fantasy atmosphere, soft glowing light, magical particles, celestial", "neg": "dark, scary, industrial", "str": 0.60},
36
+ }
37
+
38
+ V1_KEYS = list(PANEL_V1_PRESETS.keys())
39
+ V2_KEYS = list(PANEL_V2_PRESETS.keys())
40
+
41
+ # -----------------------------
42
+ # 2. System & Model Setup
43
  # -----------------------------
44
 
45
  class MockPipe:
46
  """A dummy pipeline for testing without a GPU."""
47
  def __call__(self, *args, **kwargs):
48
+ time.sleep(1.0) # Simulate "thinking" time
49
  color = kwargs.get('color_hint', 'red')
50
  return type('obj', (object,), {'images': [Image.new('RGB', (512, 512), color=color)]})
51
 
 
64
  requires_safety_checker=False
65
  ).to(device)
66
  else:
 
67
  pipe = MockPipe()
68
  print("⚠️ GPU not found. Using MockPipe for UI demonstration.")
69
  except Exception as e:
70
  print(f"⚠️ Model failed to load. Using MockPipe. Error: {e}")
71
  pipe = MockPipe()
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  class AriaAgent:
74
  def __init__(self, pipe, device):
75
  self.pipe = pipe
 
77
 
78
  def generate_reasoning(self, phase, tool_name, strength, user_intent):
79
  """Generates 'Chain of Thought' internal monologue text."""
80
+
81
+ # Fallback if user prompt is empty
82
+ context_intent = user_intent if user_intent.strip() else "Artistic Enhancement"
83
+
84
  if phase == "analysis":
85
  return (
86
  f"πŸ’­ THOUGHT: Analyzing input signal data...\n"
87
+ f" > Observation: User semantic intent: '{context_intent}'\n"
88
  f" > Assessment: Input image requires stylistic abstraction.\n"
89
+ f" > Strategy: Split task -> Structure (Step 1) + Atmosphere (Step 2)."
90
  )
91
  elif phase == "step1":
92
  return (
93
  f"πŸ’­ THOUGHT: Executing Foundation Layer.\n"
94
  f" > Selection: Tool '{tool_name}' chosen to break photorealism.\n"
95
  f" > Parameter Reasoning: Setting denoising strength to {strength:.2f}.\n"
96
+ f" - Rationale: Overwriting original textures while keeping composition.\n"
97
  f" > Action: Injecting latent noise vectors..."
98
  )
99
  elif phase == "step2":
100
  return (
101
  f"πŸ’­ THOUGHT: Refining Atmospheric Context.\n"
102
  f" > Selection: Tool '{tool_name}' chosen for lighting and mood.\n"
103
+ f" > Parameter Reasoning: Reducing strength to {strength:.2f} to preserve Step 1 strokes.\n"
104
+ f" > Optimization: Aligning vector guidance with '{context_intent}'.\n"
105
  f" > Action: Final render pass initiating."
106
  )
107
  return ""
108
 
109
  def generate(self, image, prompt, neg, strength, steps, guide, seed):
 
110
  if isinstance(self.pipe, MockPipe):
111
  color = '#8b5cf6' if "Style" in prompt else '#10b981'
112
  return self.pipe(color_hint=color).images[0]
113
 
 
114
  with torch.inference_mode():
115
  image = image.resize((DEFAULT_SIZE, DEFAULT_SIZE))
116
  gen = torch.Generator(device=self.device).manual_seed(seed)
 
134
 
135
  if init_img is None:
136
  raise gr.Error("Please upload an input image first.")
137
+
138
  # 1. Initialization
139
  if rnd: seed = random.randint(0, MAX_SEED)
140
  gallery_state.append((init_img, "1. Input Signal"))
141
 
142
  # --- COT: Analysis Phase ---
143
+ analysis_thought = agent.generate_reasoning("analysis", "", 0, user_p)
144
  logs.append(analysis_thought)
145
  yield "\n\n".join(logs), gallery_state, seed, "πŸ€” ANALYZING"
146
+ time.sleep(0.5)
147
 
148
  # --- COT: Step 1 Planning ---
149
+ # Safety check for keys
150
+ if v1_key not in PANEL_V1_PRESETS: v1_key = V1_KEYS[0]
151
  p1 = PANEL_V1_PRESETS[v1_key]
152
+
153
  final_str_1 = min(1.0, p1['str'] * strength_mult)
154
 
155
  step1_thought = agent.generate_reasoning("step1", v1_key, final_str_1, user_p)
 
164
  yield "\n\n".join(logs), gallery_state, seed, "πŸ‘€ OBSERVING"
165
 
166
  # --- COT: Step 2 Planning ---
167
+ if v2_key not in PANEL_V2_PRESETS: v2_key = V2_KEYS[0]
168
  p2 = PANEL_V2_PRESETS[v2_key]
169
+
170
  step2_thought = agent.generate_reasoning("step2", v2_key, p2['str'], user_p)
171
  logs.append(step2_thought)
172
  yield "\n\n".join(logs), gallery_state, seed, "🌫️ ATMOSPHERE"
 
196
  text-shadow: 0 0 10px rgba(56, 189, 248, 0.5);
197
  }
198
 
199
+ /* Bright Amber Subtitle for Visibility */
200
  .subtitle {
201
  font-family: 'Space Mono', monospace;
202
+ color: #fbbf24; /* Amber */
203
  font-weight: bold;
204
  font-size: 1.0rem;
205
  letter-spacing: 1px;
 
222
  }
223
  #run-btn:hover { transform: scale(1.02); box-shadow: 0 0 25px rgba(139, 92, 246, 0.7); }
224
 
 
225
  #log-output-box textarea {
226
  background-color: #0d1117 !important;
227
+ color: #4ade80 !important; /* Matrix Green */
228
  font-family: 'Space Mono', monospace !important;
229
  font-size: 0.85rem !important;
230
  border: 1px solid #30363d !important;
 
257
  with gr.Row(elem_classes="header-row"):
258
  with gr.Column(scale=6):
259
  gr.Markdown(f"# 🧬 {APP_TITLE}")
 
260
  gr.HTML(f"<span class='subtitle'>{APP_SUBTITLE}</span>")
261
  with gr.Column(scale=2):
262
  status_display = gr.Textbox(value="🟒 SYSTEM READY", label="Agent Status", interactive=False, elem_id="status-bar")
 
274
  gr.Markdown("### πŸ•ΉοΈ 2. Parameters")
275
  user_prompt = gr.Textbox(label="Creative Guidance", placeholder="E.g. 'A futuristic city at night'...", lines=2)
276
 
277
+ # Dropdowns placed here. interactive=True is KEY.
278
  with gr.Row():
279
+ v1_select = gr.Dropdown(
280
+ label="Tool A: Foundation",
281
+ choices=V1_KEYS,
282
+ value=V1_KEYS[0],
283
+ interactive=True,
284
+ min_width=150
285
+ )
286
+ v2_select = gr.Dropdown(
287
+ label="Tool B: Atmosphere",
288
+ choices=V2_KEYS,
289
+ value=V2_KEYS[0],
290
+ interactive=True,
291
+ min_width=150
292
+ )
293
 
294
  strength_mult_slide = gr.Slider(label="Concept Divergence", minimum=0.2, maximum=1.0, value=0.9, step=0.05)
295