onenoly11 commited on
Commit
d1abead
·
verified ·
1 Parent(s): 9a4f6bf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -433
app.py CHANGED
@@ -1,438 +1,149 @@
1
- import os
2
  import gradio as gr
3
- import requests
4
- import random
5
- import time
6
  from datetime import datetime
7
- from typing import Optional
8
 
9
- # API Keys
10
- XAI_API_KEY = os.environ.get('XAI_API_KEY')
11
- RUNWAY_API_KEY = os.environ.get('RUNWAY_API_KEY')
12
-
13
- # Expanded movie database (unchanged)
14
- MOVIE_TEMPLATES = {
15
- "epic_fantasy": {
16
- "title": "🏰 Epic Fantasy Quest",
17
- "examples": [
18
- "A hobbit's quest to destroy a powerful ring",
19
- "A young wizard's journey to defeat a dark lord",
20
- ]
21
- },
22
- "sci_fi_adventure": {
23
- "title": "🚀 Sci-Fi Space Opera",
24
- "examples": [
25
- "A starship crew exploring unknown galaxies",
26
- "First contact with an alien civilization"
27
- ]
28
- },
29
- "action_thriller": {
30
- "title": "💥 High-Octane Action",
31
- "examples": [
32
- "A rogue agent's global chase against a shadow cabal",
33
- "Undercover cop vs. cartel kingpin in neon-lit streets"
34
- ]
35
- },
36
- "horror_mystery": {
37
- "title": "👻 Chilling Horror",
38
- "examples": [
39
- "A haunted house awakens ancient curses",
40
- "Small-town vanishings reveal a cult's dark secret"
41
- ]
42
- },
43
- "rom_com": {
44
- "title": "❤️ Romantic Comedy",
45
- "examples": [
46
- "Fake dating turns real amid wedding chaos",
47
- "Rival chefs spark love in a culinary showdown"
48
- ]
49
- }
50
  }
51
-
52
- # Top 2025 actors (unchanged)
53
- TOP_ACTORS = [
54
- "Tom Holland", "Dwayne Johnson", "Tom Cruise", "Chris Hemsworth", "Pedro Pascal",
55
- "Robert Downey Jr.", "Will Smith", "Jason Statham", "Rachel Zegler", "Eiza González",
56
- "Monica Barbaro", "Sophie Wilde", "Joseph Quinn", "David Corenswet"
57
- ]
58
-
59
- # MPAA ratings (unchanged)
60
- MPAA_RATINGS = ["G", "PG", "PG-13", "R", "NC-17"]
61
-
62
- def test_connection():
63
- """Test xAI connection (unchanged)"""
64
- if not XAI_API_KEY:
65
- return "❌ API key not found in environment", "🔴 Offline"
66
-
67
- headers = {'Authorization': f'Bearer {XAI_API_KEY}'}
68
- try:
69
- response = requests.get('https://api.x.ai/v1/models', headers=headers, timeout=10)
70
- if response.status_code == 200:
71
- return "✅ xAI Connected! Ready for production! 🎬", "🟢 Online"
72
- else:
73
- return f"❌ API Error: {response.status_code} - {response.text}", "🔴 Offline"
74
- except Exception as e:
75
- return f" Connection error: {str(e)}", "🔴 Offline"
76
-
77
- def test_runway_connection():
78
- """Test Runway ML connection"""
79
- if not RUNWAY_API_KEY:
80
- return "❌ Runway API key not found", "🔴 Offline"
81
-
82
- headers = {'Authorization': f'Bearer {RUNWAY_API_KEY}', 'Content-Type': 'application/json'}
83
- base_url = 'https://api.runwayml.com/v1'
84
- try:
85
- # Simple ping: GET /tasks (or models if available; using a safe endpoint)
86
- response = requests.get(f"{base_url}/tasks", headers=headers, timeout=10)
87
- if response.status_code == 200 or response.status_code == 401: # 401 ok for auth test
88
- return "✅ Runway Connected! Videos incoming... 🎞️", "🟢 Online"
89
- else:
90
- return f"❌ Runway Error: {response.status_code}", "🔴 Offline"
91
- except Exception as e:
92
- return f"❌ Runway Connection error: {str(e)}", "🔴 Offline"
93
-
94
- def generate_cinematic_story(original_story, sequel_start, selected_actors, extras, story_type="epic_fantasy"):
95
- """Generate story (unchanged from v2)"""
96
- if not original_story or not sequel_start:
97
- return "❌ Please fill in both story fields!"
98
-
99
- # Cast lead/support
100
- lead_actor = random.choice(selected_actors) if selected_actors else random.choice(TOP_ACTORS)
101
- support_actors = [a for a in selected_actors if a != lead_actor][:2]
102
-
103
- # Random rating based on genre
104
- rating = random.choice(["PG-13", "R"] if "horror" in story_type or "action" in story_type else MPAA_RATINGS)
105
-
106
- headers = {
107
- 'Authorization': f'Bearer {XAI_API_KEY}',
108
- 'Content-Type': 'application/json'
109
- }
110
-
111
- # Enhanced prompt with actors, extras, genre
112
- extras_str = f" Include these elements: {extras}." if extras else ""
113
- actors_str = f" Cast {lead_actor} as the lead hero. Feature {', '.join(support_actors)} in supporting roles.{extras_str}"
114
-
115
- prompt = f"""
116
- Create a blockbuster movie sequel in the {story_type} genre (MPAA rating: {rating}):
117
-
118
- Original: {original_story}
119
- Sequel starts: {sequel_start}
120
- {actors_str}
121
-
122
- Write an engaging, cinematic sequel synopsis (300-400 words) with:
123
- - Strong character arcs for the lead ({lead_actor})
124
- - Key scenes: 3-5 high-stakes action/emotional beats
125
- - Plot twists from extras
126
- - Blockbuster ending hook
127
- Keep it vivid, dialogue-snappy, and ready for the big screen!
128
- """
129
-
130
- data = {
131
- 'model': 'grok-beta',
132
- 'messages': [{'role': 'user', 'content': prompt}],
133
- 'max_tokens': 600,
134
- 'temperature': 0.8
135
- }
136
-
137
- try:
138
- response = requests.post(
139
- 'https://api.x.ai/v1/chat/completions',
140
- headers=headers,
141
- json=data,
142
- timeout=30
143
- )
144
-
145
- if response.status_code == 200:
146
- result = response.json()
147
- story = result['choices'][0]['message']['content']
148
- else:
149
- story = _generate_fallback_story(original_story, sequel_start, lead_actor, support_actors, extras, story_type, rating)
150
-
151
- except Exception as e:
152
- story = _generate_fallback_story(original_story, sequel_start, lead_actor, support_actors, extras, story_type, rating)
153
-
154
- production_id = f"PROD-{random.randint(10000,99999)}-{datetime.now().strftime('%m%d')}"
155
-
156
- cast_section = f"**CAST HIGHLIGHTS:**\n• Lead: {lead_actor}\n" + "\n".join([f"• Support: {a}" for a in support_actors]) if support_actors else ""
157
-
158
- # Return story with trailer prompt extraction (key scene for video)
159
- trailer_prompt = story.split('Key scenes:')[1].split('.')[0].strip() if 'Key scenes:' in story else f"Epic {story_type} battle featuring {lead_actor}"
160
-
161
- return f"""
162
- 🎬 **PRODUCTION MEMO: {story_type.upper()} SEQUEL** 🎬
163
- **Project ID:** {production_id} | **Rating:** {rating} | **Genre:** {MOVIE_TEMPLATES[story_type]['title']}
164
-
165
- **{lead_actor}'s LEGEND CONTINUES...**
166
-
167
- {story}
168
-
169
- ---
170
- **CAST SHEET:**
171
- {cast_section}
172
-
173
- ✨ Lights, camera, sequel! Ready for trailer? 🚀
174
- **Trailer Prompt:** {trailer_prompt}
175
- """, trailer_prompt
176
-
177
- def _generate_fallback_story(original_story, sequel_start, lead_actor, support_actors, extras, story_type, rating):
178
- """Fallback (unchanged)"""
179
- extras_str = f" with twists like {extras}" if extras else ""
180
- support_str = f" alongside {', '.join(support_actors)}" if support_actors else ""
181
-
182
- if "fantasy" in story_type:
183
- plot = f"Years after {original_story}, {lead_actor} reprises the scarred warrior-king, facing a cataclysmic rift summoning shadow beasts{support_str}. {extras_str} In blistering battles across fractured realms, {lead_actor} uncovers a betrayal that tests loyalty and reignites old flames. Key scenes: A throne-room ambush, a forbidden portal chase, and an earth-shaking demon duel. Arc: From jaded ruler to unbreakable legend."
184
- elif "sci_fi" in story_type:
185
- plot = f"Post-{original_story}, {lead_actor} commands a ragtag fleet against an AI overlord devouring stars{support_str}. {extras_str} Quantum jumps and zero-G dogfights ensue, revealing a personal clone conspiracy. Key scenes: Black hole evasion, holographic interrogations, epic wormhole assault. Arc: Doubtful captain to galaxy's defiant savior."
186
- elif "action" in story_type:
187
- plot = f"After {original_story}, {lead_actor} hunts a rogue syndicate in rain-slicked megacities{support_str}. {extras_str} Explosive set-pieces include subway heists and rooftop pursuits. Key scenes: Double-cross diner shootout, armored convoy takedown, skyline finale. Arc: Lone wolf to team-forged avenger."
188
- elif "horror" in story_type:
189
- plot = f"Haunted by {original_story}, {lead_actor} investigates viral nightmares plaguing the world{support_str}. {extras_str} Creeping dread builds to possessions and ritual showdowns. Key scenes: Foggy asylum lockdown, mirror-world traps, blood-moon ritual. Arc: Skeptic to harbinger of the damned."
190
- else: # rom_com
191
- plot = f"Following {original_story}, {lead_actor} navigates love's chaos at a luxury resort{support_str}. {extras_str} Mishaps like mistaken identities and beachside confessions spark hilarity. Key scenes: Awkward speed-dating fiasco, midnight dance mix-up, heartfelt airport dash. Arc: Commitment-phobe to forever optimist."
192
-
193
- return f"**SYNOPSIS:** {plot}\n\n**Why It Works:** High-stakes{ ' + emotional depth' if 'rom' in story_type else ''}, perfect for {rating} crowds. Budget: $150M. Greenlight now!\n**Key scenes:** {plot.split('Key scenes:')[1] if 'Key scenes:' in plot else 'Epic showdown.'}"
194
-
195
- def generate_movie_pitch(selected_actors=None):
196
- """Pitch (unchanged)"""
197
- if not selected_actors:
198
- selected_actors = random.sample(TOP_ACTORS, 3)
199
-
200
- genres = list(MOVIE_TEMPLATES.keys())
201
- selected_genre = random.choice(genres)
202
- template = MOVIE_TEMPLATES[selected_genre]
203
-
204
- lead = selected_actors[0]
205
- supports = selected_actors[1:]
206
- rating = random.choice(MPAA_RATINGS)
207
-
208
- logline = random.choice(template['examples'])
209
- franchise_potential = '🟢 HIGH' if random.random() > 0.5 else '🟡 MEDIUM'
210
-
211
- trailer_prompt = f"{logline} - cinematic trailer shot with dramatic music."
212
-
213
- pitch = f"""
214
- 🎬 **GREENLIGHT PITCH DECK** 🎬
215
-
216
- **GENRE:** {template['title']} | **RATING:** {rating}
217
- **LOGLINE:** {logline} — Starring {lead} as the unbreakable hero, with {', '.join(supports)} lighting up the ensemble.
218
-
219
- **BUDGET:** ${random.randint(80,250)}M
220
- **TIMELINE:** {random.randint(18,36)} months to cameras
221
- **TARGET AUDIENCE:** {random.randint(13,35)}+ thrill-seekers/romantics
222
- **FRANCHISE POTENTIAL:** {franchise_potential}
223
- **HOOK:** Explosive opener + twisty mid-act + unforgettable finale. Dir. rec: Taika Waititi for {selected_genre}.
224
-
225
- **QUICK CAST NOTES:**
226
- • {lead}: Lead (raw charisma + action chops)
227
- • {supports[0] if supports else 'TBD'}: Comic relief/foil
228
- • {supports[1] if len(supports) > 1 else 'TBD'}: Emotional anchor
229
-
230
- 🟢 **READY FOR DEVELOPMENT?** This one's a box-office beast!
231
- **Trailer Prompt:** {trailer_prompt}
232
  """
233
- return pitch, trailer_prompt
234
-
235
- def generate_video_trailer(prompt: str, duration: int = 5) -> str:
236
- """Generate video trailer using Runway ML API"""
237
- if not RUNWAY_API_KEY:
238
- # Fallback: Placeholder video URL (e.g., stock trailer)
239
- return "https://example.com/placeholder-trailer.mp4", "No Runway key—using demo clip. Add RUNWAY_API_KEY for real gen!"
240
-
241
- headers = {
242
- 'Authorization': f'Bearer {RUNWAY_API_KEY}',
243
- 'Content-Type': 'application/json'
244
- }
245
- base_url = 'https://api.runwayml.com/v1'
246
-
247
- # Create task (text-to-video params based on Runway docs)
248
- create_data = {
249
- "model": "gen3a_turbo", # Latest text-to-video model (2025)
250
- "text_prompt": prompt + " | Cinematic trailer style, dramatic lighting, high-energy action, epic music swell.",
251
- "seconds": duration,
252
- "aspect_ratio": "16:9",
253
- "turbo": True, # Faster gen
254
- "explore_mode": True # More creative
255
- }
256
-
257
- try:
258
- # Start task
259
- create_resp = requests.post(f"{base_url}/text_to_video", headers=headers, json=create_data, timeout=30)
260
- create_resp.raise_for_status()
261
- task_data = create_resp.json()
262
- task_id = task_data.get('id') or task_data.get('task_id')
263
- if not task_id:
264
- raise ValueError("No task ID in response")
265
-
266
- # Poll for completion (every 10s, up to 5 min)
267
- status = "processing"
268
- for _ in range(30): # ~5 min max
269
- time.sleep(10)
270
- status_resp = requests.get(f"{base_url}/tasks/{task_id}", headers=headers, timeout=10)
271
- status_resp.raise_for_status()
272
- status_data = status_resp.json()
273
- status = status_data.get('status')
274
-
275
- if status == 'succeeded':
276
- # Extract video URL
277
- output = status_data.get('output', {})
278
- video_url = output.get('video_url') or output.get('assets', [{}])[0].get('url')
279
- if video_url:
280
- return video_url, f"✅ Trailer generated! ({duration}s clip)"
281
- else:
282
- raise ValueError("No video URL in output")
283
- elif status == 'failed':
284
- error_msg = status_data.get('error', 'Unknown error')
285
- raise Exception(f"Generation failed: {error_msg}")
286
-
287
- raise TimeoutError("Generation timed out after 5 min")
288
-
289
- except Exception as e:
290
- return None, f"❌ Error: {str(e)}. Check key/credits. Fallback: Imagine epic footage here! 🎞️"
291
-
292
- # Polished Interface (v3 with Video Tab)
293
- with gr.Blocks(title="IdeaForge Studio v3", theme=gr.themes.Base(primary_hue="amber")) as demo:
294
-
295
- gr.Markdown("""
296
- # 🎬 **IdeaForge Studio v3**
297
- ### AI Blockbusters: Stories, Pitches & Now VIDEO TRAILERS!
298
- *xAI for text + Runway ML for clips | Oct 2025 Edition.*
299
- """)
300
-
301
- # Status Row (added Runway test)
302
- with gr.Row():
303
- with gr.Column(scale=1):
304
- xai_btn = gr.Button("📡 Test xAI", variant="secondary")
305
- runway_btn = gr.Button("🎞️ Test Runway", variant="secondary")
306
- with gr.Column(scale=4):
307
- xai_msg = gr.Textbox(label="xAI Log", show_label=False, lines=1)
308
- xai_icon = gr.Textbox(label="xAI Status", show_label=False, max_lines=1)
309
- runway_msg = gr.Textbox(label="Runway Log", show_label=False, lines=1)
310
- runway_icon = gr.Textbox(label="Runway Status", show_label=False, max_lines=1)
311
-
312
- # Story Tab (updated to return prompt for trailer)
313
- with gr.Tab("🎞️ Sequel Forge"):
314
- gr.Markdown("### Craft Epic Sequels with Custom Cast")
315
-
316
- with gr.Row():
317
- with gr.Column(scale=1):
318
- original_input = gr.Textbox(
319
- label="Original Movie Logline",
320
- placeholder="e.g., Conan slays Thulsa Doom in barbaric revenge...",
321
- lines=2
322
- )
323
- sequel_input = gr.Textbox(
324
- label="Sequel Kickoff",
325
- placeholder="e.g., As King, Conan battles an ice demon's curse...",
326
- lines=2
327
- )
328
- story_type_dropdown = gr.Dropdown(
329
- choices=list(MOVIE_TEMPLATES.keys()),
330
- value="epic_fantasy",
331
- label="Genre Vibes"
332
- )
333
- extras_input = gr.Textbox(
334
- label="Add Twists/Elements",
335
- placeholder="e.g., time-travel betrayal, zombie allies",
336
- lines=1
337
- )
338
- actor_select = gr.CheckboxGroup(
339
- choices=TOP_ACTORS,
340
- label="Cast Your Stars (pick 1-3)",
341
- value=[TOP_ACTORS[0]],
342
- interactive=True
343
- )
344
-
345
- with gr.Column(scale=1):
346
- gr.Markdown("### Quick Load")
347
- gr.Button("🗡️ Conan Classic").click(
348
- lambda: ([
349
- "Conan the Barbarian seeks revenge against Thulsa Doom for destroying his village",
350
- "Years later, King Conan faces an ancient ice demon awakening in the frozen north",
351
- "epic_fantasy",
352
- "magical artifacts, betrayal by advisor",
353
- ["Dwayne Johnson", "Pedro Pascal"]
354
- ]),
355
- outputs=[original_input, sequel_input, story_type_dropdown, extras_input, actor_select]
356
- )
357
- gr.Button("🚀 Star Wars Vibes").click(
358
- lambda: ([
359
- "A farm boy joins rebels to destroy the Death Star",
360
- "Post-victory, the hero uncovers a Sith family secret",
361
- "sci_fi_adventure",
362
- "force ghost mentors, twin reveal",
363
- ["Tom Holland", "Joseph Quinn"]
364
- ]),
365
- outputs=[original_input, sequel_input, story_type_dropdown, extras_input, actor_select]
366
- )
367
-
368
- generate_btn = gr.Button("🎬 Generate Full Sequel!", variant="primary", size="lg")
369
- story_output = gr.Markdown(label="Your Blockbuster Bible")
370
- trailer_prompt_hidden = gr.Textbox(visible=False) # Hidden for chaining
371
-
372
- generate_btn.click(
373
- generate_cinematic_story,
374
- inputs=[original_input, sequel_input, actor_select, extras_input, story_type_dropdown],
375
- outputs=[story_output, trailer_prompt_hidden]
376
- )
377
-
378
- # Pitch Tab (updated to return prompt)
379
- with gr.Tab("💡 Pitch Roulette"):
380
- gr.Markdown("### Instant Greenlight Concepts")
381
-
382
- with gr.Row():
383
- pitch_actor_select = gr.CheckboxGroup(
384
- choices=TOP_ACTORS,
385
- label="Dream Cast (optional)",
386
- value=[],
387
- interactive=True
388
- )
389
- gr.Button("🎲 Roll Random Cast", variant="secondary").click(
390
- lambda: random.sample(TOP_ACTORS, random.randint(1,3)),
391
- outputs=pitch_actor_select
392
- )
393
-
394
- pitch_btn = gr.Button("✨ Generate Pitch Deck!", variant="primary")
395
- pitch_output = gr.Markdown(label="Hot Pitch")
396
- pitch_prompt_hidden = gr.Textbox(visible=False)
397
-
398
- pitch_btn.click(generate_movie_pitch, inputs=[pitch_actor_select], outputs=[pitch_output, pitch_prompt_hidden])
399
-
400
- # NEW: Video Trailer Tab
401
- with gr.Tab("🎥 Trailer Forge"):
402
- gr.Markdown("### AI-Generated Video Trailers via Runway ML")
403
- gr.Markdown("*Paste a story prompt below—watch it come alive! ~2-5 min gen time.*")
404
-
405
- trailer_prompt_input = gr.Textbox(
406
- label="Trailer Prompt",
407
- placeholder="e.g., King Conan battles ice demons in frozen wastelands, epic sword fight...",
408
- lines=3,
409
- value="Cinematic fantasy battle in snowy mountains"
410
- )
411
- duration_slider = gr.Slider(5, 10, value=5, step=1, label="Clip Length (seconds)")
412
- gen_video_btn = gr.Button("🚀 Generate Trailer!", variant="primary")
413
-
414
- video_output = gr.Video(label="Your AI Trailer", show_download_button=True)
415
- video_status = gr.Textbox(label="Status", show_label=False, lines=1)
416
-
417
- # Chain from other tabs? Optional examples
418
- gr.Examples(
419
- examples=[
420
- ["Epic space battle with starships exploding in nebula clouds"],
421
- ["Romantic comedy meet-cute in rainy Paris streets, slow-motion smiles"],
422
- ["Horror chase through haunted mansion, flickering lights and shadows"]
423
- ],
424
- inputs=trailer_prompt_input
425
- )
426
-
427
- gen_video_btn.click(
428
- generate_video_trailer,
429
- inputs=[trailer_prompt_input, duration_slider],
430
- outputs=[video_output, video_status]
431
- )
432
-
433
- # Connections
434
- xai_btn.click(test_connection, outputs=[xai_msg, xai_icon])
435
- runway_btn.click(test_runway_connection, outputs=[runway_msg, runway_icon])
436
-
437
- if __name__ == "__main__":
438
- demo.launch(share=True)
 
 
1
  import gradio as gr
2
+ import hashlib, matplotlib.pyplot as plt, numpy as np
 
 
3
  from datetime import datetime
 
4
 
5
+ # CSS
6
+ PIFORGE_CSS = """
7
+ .piforge-premium-header{
8
+ background:linear-gradient(135deg,#FF6B6B,#FFE66D,#1A535C);
9
+ padding:30px;border-radius:20px;color:#fff;text-align:center;
10
+ margin-bottom:30px;border:4px solid #4ECDC4;box-shadow:0 10px 30px rgba(0,0,0,.3);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
12
+ .audit-badge{background:linear-gradient(45deg,#667eea,#764ba2);color:#fff;
13
+ padding:8px 16px;border-radius:20px;font-weight:bold;}
14
+ .builder-badge{background:linear-gradient(45deg,#FFD700,#FF6B00);color:#1A535C;
15
+ padding:8px 16px;border-radius:20px;font-weight:bold;}
16
+ """
17
+
18
+ # Oracle
19
+ class PiForgeQualiaOracle:
20
+ def get_qualia_score(self, txt: str) -> int:
21
+ if not txt: return 500
22
+ txt = txt.lower(); score = 500
23
+ boosts = {"community":80,"inclusion":90,"transparent":85,"fair":80,
24
+ "privacy":75,"education":75,"help":70,"empower":85,
25
+ "decentralized":65,"open":70,"accessible":75}
26
+ for w,b in boosts.items():
27
+ if w in txt: score += b
28
+ score += min(200, len(txt)//2)
29
+ return min(1000, max(0, score))
30
+ qualia_oracle = PiForgeQualiaOracle()
31
+
32
+ # Core
33
+ def velvet_verdict(a,b): a,b=int(a),int(b); return 0 if a==0 or b==0 else (2*a*b)//(a+b)
34
+ def resonance_narrative(r):
35
+ if r>=800: return "Resonance blooms: Sovereign sway achieved"
36
+ if r>=650: return "Synthesis stirs: Tender truth tempers the tide"
37
+ if r>=500: return "Echo invites: A gentle balance"
38
+ return "Refine the reactive, reflect the reflection"
39
+
40
+ def plot_triad(v,q,r):
41
+ labels = ['Veracity','Qualia','Resonance']
42
+ scores = [v/1000,q/1000,r/1000]
43
+ angles = np.linspace(0,2*np.pi,len(labels),endpoint=False).tolist()
44
+ scores += scores[:1]; angles += angles[:1]
45
+ fig,ax = plt.subplots(figsize=(6,6),subplot_kw=dict(polar=True))
46
+ ax.plot(angles,scores,color='magenta',lw=2)
47
+ ax.fill(angles,scores,color='cyan',alpha=.25)
48
+ ax.set_xticks(angles[:-1]); ax.set_xticklabels(labels); ax.set_yticklabels([])
49
+ ax.set_facecolor('#1a1a1a'); fig.patch.set_facecolor('#1a1a1a')
50
+ plt.title('Ethical Triad Harmony',size=14,color='white',y=1.1)
51
+ return fig
52
+
53
+ # Audit Functions
54
+ def simple_ethics_check(name,desc,impact):
55
+ if not desc: return 0,"Please describe your project","Waiting..."
56
+ q = qualia_oracle.get_qualia_score(impact+" "+desc)
57
+ eff = min(800, len(desc)*2+400)
58
+ res = velvet_verdict(eff,q)
59
+ if res>=850: v,conf = "EXCELLENT!",f"{res}/1000 - Community-ready!"
60
+ elif res>=700: v,conf = "VERY GOOD",f"{res}/1000 - Solid"
61
+ elif res>=550: v,conf = "GOOD",f"{res}/1000 - Refine"
62
+ else: v,conf = "NEEDS WORK",f"{res}/1000 - Rethink"
63
+ return res, v, conf
64
+
65
+ def traverse_triad(reactive, impact_txt):
66
+ reac = int(reactive)
67
+ qual = qualia_oracle.get_qualia_score(impact_txt)
68
+ res = velvet_verdict(reac, qual)
69
+ return (f"Reactive: {reac}/1000",
70
+ f"Qualia: {qual}/1000",
71
+ f"Resonance: {res}/1000",
72
+ resonance_narrative(res),
73
+ plot_triad(reac,qual,res))
74
+
75
+ # App Builder
76
+ class PiForgeAppBuilder:
77
+ def generate_testnet_app(self,idea,typ,feats):
78
+ base = 5
79
+ boosts = {"community_governance":3,"pi_rewards":2}
80
+ total = base + sum(boosts.get(f,0) for f in feats)
81
+ return {"boost":min(15,total),
82
+ "id":f"testnet_{hashlib.sha256(f'{idea}{datetime.now()}'.encode()).hexdigest()[:12]}"}
83
+ app_builder = PiForgeAppBuilder()
84
+
85
+ def build_testnet_app(idea,typ,feats):
86
+ if not idea: return "Enter idea","","0","",""
87
+ data = app_builder.generate_testnet_app(idea,typ,feats)
88
+ eth = qualia_oracle.get_qualia_score(f"{idea} with {feats}")
89
+ bp = f"""
90
+ Testnet App Blueprint
91
+ Ethical Score: {eth}/1000
92
+ Mining Boost: +{data['boost']}%
93
+ App ID: {data['id']}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  """
95
+ return "Generated!",bp,data['boost'],data['id']
96
+
97
+ # UI
98
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue="violet"), css=PIFORGE_CSS) as demo:
99
+ gr.HTML("""
100
+ <div class="piforge-premium-header">
101
+ <h1>π PiForge Dual-Platform</h1>
102
+ <h3>Ethical Audit + AI App Builder</h3>
103
+ <p><span class='audit-badge'>AUDIT</span> <span class='builder-badge'>BUILD</span></p>
104
+ </div>""")
105
+
106
+ with gr.Tabs():
107
+ with gr.Tab("Ethical Audit"):
108
+ with gr.Tab("Simple"):
109
+ with gr.Row():
110
+ with gr.Column():
111
+ p_name = gr.Textbox("Community Marketplace", label="Project Name")
112
+ desc = gr.Textbox(lines=3, label="Description")
113
+ impact = gr.Textbox(lines=2, label="Impact")
114
+ btn = gr.Button("Run Audit", variant="primary")
115
+ with gr.Column():
116
+ score = gr.Number(label="Score")
117
+ verd = gr.Textbox(lines=2, label="Verdict")
118
+ anal = gr.Textbox(lines=3, label="Analysis")
119
+ btn.click(simple_ethics_check, [p_name,desc,impact], [score,verd,anal])
120
+
121
+ with gr.Tab("Expert"):
122
+ with gr.Row():
123
+ with gr.Column():
124
+ reactive = gr.Slider(0,1000,700,label="Reactive")
125
+ impact_t = gr.Textbox(lines=3,label="Impact")
126
+ exp_btn = gr.Button("Traverse",variant="primary")
127
+ with gr.Column():
128
+ v_out = gr.Textbox(label="Reactive")
129
+ q_out = gr.Textbox(label="Qualia")
130
+ r_out = gr.Textbox(label="Resonance")
131
+ nar = gr.Textbox(label="Narrative")
132
+ plot = gr.Plot()
133
+ exp_btn.click(traverse_triad,[reactive,impact_t],[v_out,q_out,r_out,nar,plot])
134
+
135
+ with gr.Tab("AI App Builder"):
136
+ with gr.Row():
137
+ with gr.Column():
138
+ idea = gr.Textbox(lines=3,label="App Idea")
139
+ typ = gr.Dropdown(["marketplace","education","gaming"],label="Type")
140
+ feats = gr.CheckboxGroup(["community_governance","pi_rewards"],label="Features")
141
+ bbtn = gr.Button("Build",variant="primary")
142
+ with gr.Column():
143
+ status = gr.Textbox(label="Status")
144
+ bp = gr.Textbox(lines=6,label="Blueprint")
145
+ boost = gr.Number(label="Boost %")
146
+ aid = gr.Textbox(label="App ID")
147
+ bbtn.click(build_testnet_app,[idea,typ,feats],[status,bp,boost,aid])
148
+
149
+ demo.launch()