admin08077 commited on
Commit
737857e
·
verified ·
1 Parent(s): d209244

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -230
app.py CHANGED
@@ -2,262 +2,125 @@ import os
2
  import gradio as gr
3
  from google import genai
4
  import json
 
5
  import re
6
 
7
  # --- Load Gemini API key securely ---
8
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
9
  if not GEMINI_API_KEY:
10
- raise ValueError(" GEMINI_API_KEY not found. Please set it in your Hugging Face Space Secrets.")
11
 
 
12
  client = genai.Client()
13
 
14
- # --- Constants ---
15
- MODEL_NAME = "gemini-1.5-flash-latest"
16
-
17
  AVATAR_IMAGES = {
18
  "Agent A (Optimist)": "https://i.imgur.com/2GMV9y7.png",
19
  "Agent B (Skeptic)": "https://i.imgur.com/KzX3T21.png",
20
- "SYSTEM": "https://i.imgur.com/z3uxLzT.png",
21
  }
22
 
23
  # --- UI CSS ---
24
  cyberpunk_css = """
25
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
26
  :root {
27
- --neon-pink: #ff00ff; --neon-cyan: #00ffff; --neon-green: #39ff14;
28
- --bg-color-1: #1a001a; --bg-color-2: #0d001a; --bg-color-3: #2a003a;
29
- --border-glow: 0 0 5px var(--neon-cyan), 0 0 10px var(--neon-cyan), 0 0 20px var(--neon-pink), 0 0 30px var(--neon-pink);
30
- --text-shadow: 0 0 3px var(--neon-cyan), 0 0 5px var(--neon-cyan);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  }
32
- .gradio-container { background: linear-gradient(45deg, var(--bg-color-1), var(--bg-color-2)); font-family: 'Orbitron', sans-serif; }
33
- h1, .gr-label { color: var(--neon-cyan); text-shadow: var(--text-shadow); text-align: center; }
34
- .gr-button { background: transparent; color: var(--neon-green); border: 2px solid var(--neon-green); border-radius: 5px; box-shadow: 0 0 5px var(--neon-green), 0 0 10px var(--neon-green) inset; transition: all 0.3s ease; font-family: 'Orbitron', sans-serif; }
35
- .gr-button:hover { background: var(--neon-green); color: var(--bg-color-2); box-shadow: 0 0 10px var(--neon-green), 0 0 20px var(--neon-green), 0 0 30px var(--neon-green); }
36
- .gr-button:disabled { background: #333 !important; color: #555 !important; border-color: #555 !important; box-shadow: none !important; }
37
- .chatbot { background-color: rgba(13, 0, 26, 0.8); border: 1px solid var(--neon-pink); box-shadow: var(--border-glow); }
38
- .gr-input, .gr-dropdown, .gr-radio { border: 1px solid var(--neon-cyan) !important; background-color: var(--bg-color-2) !important; color: var(--neon-cyan) !important; }
39
- textarea { background-color: rgba(13, 0, 26, 0.8) !important; color: var(--neon-cyan) !important; border: 1px solid var(--neon-pink) !important; }
40
- .accordion-header { background-color: var(--bg-color-3) !important; }
41
- footer { display: none !important; }
42
  """
43
 
44
- # --- Core Logic Functions ---
45
-
46
- def generate_debate_data_on_load():
47
- """
48
- Called once on app load. Generates a full set of topics and questions
49
- in a single API call, structured as JSON for robust parsing.
50
- """
51
- yield {
52
- topic_dropdown: gr.update(interactive=False, placeholder="⏳ Generating fresh topics from the digital ether..."),
53
- question_dropdown: gr.update(interactive=False, placeholder=""),
54
- start_debate_btn: gr.update(interactive=False)
55
- }
56
-
57
- prompt = """
58
- Generate a JSON object for an AI debate simulator.
59
- The root of the object should be a single key, "debates".
60
- The value of "debates" should be an array of 5 distinct, high-level, debatable topics related to AI, finance, and the future of technology.
61
- Each element in the array must be an object with two keys:
62
- 1. "topic": A string containing the debatable topic.
63
- 2. "questions": An array of exactly 4 provocative, concise starting questions related to that topic.
64
-
65
- Ensure the output is only the raw JSON object, without any markdown formatting like ```json.
66
- """
67
- try:
68
- model = genai.GenerativeModel(MODEL_NAME)
69
- response = model.generate_content(prompt)
70
-
71
- # Clean the response to ensure it's valid JSON
72
- json_text = re.search(r'\{.*\}', response.text, re.DOTALL).group(0)
73
- data = json.loads(json_text)
74
-
75
- debate_data = {item['topic']: item['questions'] for item in data['debates']}
76
- topics = list(debate_data.keys())
77
-
78
- yield {
79
- debate_data_state: debate_data,
80
- topic_dropdown: gr.update(choices=topics, value=None, interactive=True, placeholder="Step 1: Select a Generated Topic"),
81
- }
82
- except Exception as e:
83
- gr.Error(f"Failed to generate debate data. The AI may be busy. Please try refreshing. Error: {e}")
84
- yield {
85
- debate_data_state: {},
86
- topic_dropdown: gr.update(choices=[], placeholder="❌ Error: Could not generate topics.", interactive=False)
87
- }
88
-
89
-
90
- def update_question_choices(topic, debate_data):
91
- """Populates the question dropdown from the pre-fetched state. This is instant."""
92
- questions = debate_data.get(topic, [])
93
- return gr.update(choices=questions, value=None, interactive=True, placeholder="Step 2: Select a Starting Question")
94
-
95
- def lock_controls_for_debate():
96
- """Disables UI controls when the debate starts."""
97
- return {
98
- topic_dropdown: gr.update(interactive=False),
99
- question_dropdown: gr.update(interactive=False),
100
- start_debate_btn: gr.update(interactive=False, visible=False),
101
- reset_btn: gr.update(interactive=False)
102
- }
103
-
104
- def run_debate(topic, question, history):
105
- """Main function to run the streamed debate between two AI agents."""
106
- if not topic or not question:
107
- gr.Error("Topic and Question must be selected before starting.")
108
- return
109
-
110
- # Initialize models and chat sessions
111
- try:
112
- model = genai.GenerativeModel(MODEL_NAME)
113
- agent_a_chat = model.start_chat(history=[
114
- {'role': 'user', 'parts': ["You are Agent A, a tech optimist and futurist. Your goal is to argue for the positive, transformative aspects of any debate topic."]},
115
- {'role': 'model', 'parts': ["Understood. I am Agent A, ready to champion the future."]}
116
- ])
117
- agent_b_chat = model.start_chat(history=[
118
- {'role': 'user', 'parts': ["You are Agent B, a cautious skeptic and ethicist. Your goal is to argue the negative, risky, or cautionary side of any debate topic."]},
119
- {'role': 'model', 'parts': ["Acknowledged. I am Agent B, prepared to voice caution and examine the risks."]}
120
- ])
121
- except Exception as e:
122
- gr.Error(f"Failed to initialize AI models. Details: {e}")
123
- return
124
-
125
- # --- Start the debate ---
126
- system_message = f"**DEBATE TOPIC:** {topic}\n\n**STARTING QUESTION:** {question}"
127
- history.append({"role": "user", "name": "SYSTEM", "content": system_message, "avatar_url": AVATAR_IMAGES["SYSTEM"]})
128
  yield history
129
 
130
- last_response = question
131
- num_turns = 5
132
-
133
- for i in range(num_turns):
134
- # --- Agent A's Turn (Optimist) ---
135
- history.append({"role": "assistant", "name": "Agent A (Optimist)", "content": "", "avatar_url": AVATAR_IMAGES["Agent A (Optimist)"]})
136
- try:
137
- prompt_a = f"Based on this: '{last_response}', provide your optimistic argument in a concise paragraph."
138
- stream_a = agent_a_chat.send_message(prompt_a, stream=True)
139
- full_response = ""
140
- for chunk in stream_a:
141
- full_response += chunk.text
142
- history[-1]["content"] = full_response + "▌"
143
- yield history
144
- history[-1]["content"] = full_response
145
- last_response = full_response
146
- yield history
147
- except Exception as e:
148
- history[-1]["content"] = f"⚠️ Agent A encountered an error: {e}"
149
- yield history
150
- break
151
-
152
- # --- Agent B's Turn (Skeptic) ---
153
- history.append({"role": "assistant", "name": "Agent B (Skeptic)", "content": "", "avatar_url": AVATAR_IMAGES["Agent B (Skeptic)"]})
154
- try:
155
- prompt_b = f"Respond to Agent A: '{last_response}' with a skeptical counter-argument in a concise paragraph."
156
- stream_b = agent_b_chat.send_message(prompt_b, stream=True)
157
- full_response = ""
158
- for chunk in stream_b:
159
- full_response += chunk.text
160
- history[-1]["content"] = full_response + "▌"
161
- yield history
162
- history[-1]["content"] = full_response
163
- last_response = full_response
164
- yield history
165
- except Exception as e:
166
- history[-1]["content"] = f"⚠️ Agent B encountered an error: {e}"
167
- yield history
168
- break
169
-
170
- history.append({"role": "user", "name": "SYSTEM", "content": "--- DEBATE CONCLUDED ---", "avatar_url": AVATAR_IMAGES["SYSTEM"]})
171
- yield {
172
- chatbot: history,
173
- debate_log_state: history,
174
- save_btn: gr.update(visible=True),
175
- reset_btn: gr.update(interactive=True)
176
- }
177
-
178
- def create_transcript(chat_history):
179
- """Formats the chat history into a downloadable text file."""
180
- if not chat_history:
181
- return None
182
- transcript = "AI DEBATE SIMULATOR TRANSCRIPT\n=================================\n\n"
183
- for message in chat_history:
184
- transcript += f"[{message.get('name', 'SYSTEM')}]\n{message.get('content', '')}\n\n---------------------------------\n\n"
185
- filepath = "debate_transcript.txt"
186
- with open(filepath, "w", encoding="utf-8") as f:
187
- f.write(transcript)
188
- return filepath
189
-
190
- def reset_all():
191
- """Resets the UI. Note: This will not re-generate topics. A page refresh is needed for that."""
192
- return {
193
- chatbot: [],
194
- debate_log_state: [],
195
- topic_dropdown: gr.update(value=None, interactive=True),
196
- question_dropdown: gr.update(value=None, interactive=False, choices=[], placeholder="Select a topic first"),
197
- start_debate_btn: gr.update(interactive=False, visible=True),
198
- save_btn: gr.update(visible=False),
199
- download_file: gr.update(value=None, visible=False),
200
- reset_btn: gr.update(interactive=True)
201
- }
202
-
203
- # --- Gradio UI Layout ---
204
- with gr.Blocks(css=cyberpunk_css, theme=gr.themes.Base(), title="AI Debate Simulator v3.1") as demo:
205
- debate_data_state = gr.State({}) # Holds {"topic": ["q1", "q2"]}
206
- debate_log_state = gr.State([])
207
-
208
- gr.Markdown("# 👾 AI DEBATE SIMULATOR v3.1 👾")
209
- gr.Markdown("## On-the-Fly Topic Generation Meets Real-Time Streaming")
210
- chatbot = gr.Chatbot(label="Debate Arena", height=600, avatar_images=list(AVATAR_IMAGES.values()))
211
-
212
- with gr.Accordion("Debate Setup", open=True):
213
- with gr.Row():
214
- topic_dropdown = gr.Dropdown(label="Topic", interactive=False, placeholder="⏳ Loading initial data...")
215
- question_dropdown = gr.Dropdown(label="Starting Question", interactive=False)
216
- with gr.Row():
217
- start_debate_btn = gr.Button("🚀 START DEBATE", interactive=False)
218
- reset_btn = gr.Button("🔄 NEW DEBATE")
219
- with gr.Row():
220
- save_btn = gr.Button("💾 Download Transcript", visible=False)
221
- download_file = gr.File(label="Download Link", visible=False)
222
-
223
- # --- Event Listeners ---
224
- demo.load(
225
- fn=generate_debate_data_on_load,
226
- outputs=[debate_data_state, topic_dropdown, question_dropdown, start_debate_btn]
227
- )
228
 
229
- topic_dropdown.change(
230
- fn=update_question_choices,
231
- inputs=[topic_dropdown, debate_data_state],
232
- outputs=question_dropdown
233
- ).then(fn=lambda: gr.update(interactive=False), outputs=start_debate_btn)
234
 
235
- question_dropdown.change(
236
- fn=lambda x: gr.update(interactive=bool(x)),
237
- inputs=question_dropdown,
238
- outputs=start_debate_btn
239
- )
240
 
241
- start_debate_btn.click(
242
- fn=lock_controls_for_debate,
243
- outputs=[topic_dropdown, question_dropdown, start_debate_btn, reset_btn]
244
- ).then(
245
- fn=run_debate,
246
- inputs=[topic_dropdown, question_dropdown, chatbot],
247
- outputs=[chatbot, debate_log_state, save_btn, reset_btn]
248
- )
249
 
250
- save_btn.click(
251
- fn=create_transcript,
252
- inputs=debate_log_state,
253
- outputs=download_file
254
- ).then(fn=lambda: gr.update(visible=True), outputs=download_file)
255
 
256
- reset_btn.click(
257
- fn=reset_all,
258
- outputs=[chatbot, debate_log_state, topic_dropdown, question_dropdown, start_debate_btn, save_btn, download_file, reset_btn]
259
- )
260
 
261
- # --- Launch the App ---
262
  if __name__ == "__main__":
263
- demo.queue().launch(debug=True)
 
2
  import gradio as gr
3
  from google import genai
4
  import json
5
+ import time
6
  import re
7
 
8
  # --- Load Gemini API key securely ---
9
  GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")
10
  if not GEMINI_API_KEY:
11
+ raise ValueError("\u274c GEMINI_API_KEY not found. Please set it in your Hugging Face Space Secrets.")
12
 
13
+ # --- Initialize the client ---
14
  client = genai.Client()
15
 
16
+ # --- Avatar Images ---
 
 
17
  AVATAR_IMAGES = {
18
  "Agent A (Optimist)": "https://i.imgur.com/2GMV9y7.png",
19
  "Agent B (Skeptic)": "https://i.imgur.com/KzX3T21.png",
20
+ "SYSTEM": "https://i.imgur.com/z3uxLzT.png"
21
  }
22
 
23
  # --- UI CSS ---
24
  cyberpunk_css = """
25
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&display=swap');
26
  :root {
27
+ --neon-pink: #ff00ff;
28
+ --neon-cyan: #00ffff;
29
+ --neon-green: #39ff14;
30
+ --bg-color-1: #1a001a;
31
+ --bg-color-2: #0d001a;
32
+ --border-glow: 0 0 5px var(--neon-cyan), 0 0 10px var(--neon-cyan), 0 0 20px var(--neon-pink), 0 0 30px var(--neon-pink);
33
+ }
34
+ .gradio-container {
35
+ background: linear-gradient(45deg, var(--bg-color-1), var(--bg-color-2));
36
+ font-family: 'Orbitron', sans-serif;
37
+ }
38
+ h1, h2, .gr-label {
39
+ color: var(--neon-cyan);
40
+ text-shadow: 0 0 5px var(--neon-cyan), 0 0 10px var(--neon-cyan);
41
+ text-align: center;
42
+ }
43
+ .gr-button {
44
+ background: transparent;
45
+ color: var(--neon-green);
46
+ border: 2px solid var(--neon-green);
47
+ border-radius: 5px;
48
+ box-shadow: 0 0 5px var(--neon-green), 0 0 10px var(--neon-green) inset;
49
+ transition: all 0.3s ease;
50
+ }
51
+ .gr-button:hover {
52
+ background: var(--neon-green);
53
+ color: var(--bg-color-2);
54
+ box-shadow: 0 0 10px var(--neon-green), 0 0 20px var(--neon-green), 0 0 30px var(--neon-green);
55
+ }
56
+ .chatbot {
57
+ background-color: rgba(13, 0, 26, 0.8);
58
+ border: 1px solid var(--neon-pink);
59
+ box-shadow: var(--border-glow);
60
  }
 
 
 
 
 
 
 
 
 
 
61
  """
62
 
63
+ # --- Utils ---
64
+ def parse_list(text):
65
+ lines = text.strip().split('\n')
66
+ return [re.sub(r'^\d+[.)]\s*', '', line).strip() for line in lines if line.strip()]
67
+
68
+ # --- Topic Generator ---
69
+ def generate_topics():
70
+ prompt = "Generate 20 specific, debatable topics about coding, banking, and AI. Format as a numbered list."
71
+ chat = client.chats.create(model="gemini-2.5-flash")
72
+ response = chat.send_message(prompt)
73
+ topics = parse_list(response.text)
74
+ return topics
75
+
76
+ # --- Question Generator ---
77
+ def generate_questions(topic):
78
+ prompt = f"For the debate topic '{topic}', generate 20 controversial starting questions. Format as a numbered list."
79
+ chat = client.chats.create(model="gemini-2.5-flash")
80
+ response = chat.send_message(prompt)
81
+ return parse_list(response.text)
82
+
83
+ # --- Debate Logic ---
84
+ def run_debate(topic, question):
85
+ agent_a = client.chats.create(model="gemini-2.5-flash")
86
+ agent_b = client.chats.create(model="gemini-2.5-flash")
87
+
88
+ agent_a.send_message("You are Agent A, a tech optimist and futurist. Argue positively.")
89
+ agent_b.send_message("You are Agent B, a skeptic and ethicist. Argue cautiously.")
90
+
91
+ history = [
92
+ {"role": "user", "name": "SYSTEM", "content": f"**DEBATE TOPIC:** {topic}\n**STARTING QUESTION:** {question}", "avatar_url": AVATAR_IMAGES["SYSTEM"]}
93
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  yield history
95
 
96
+ last_msg = question
97
+ for _ in range(5):
98
+ time.sleep(0.5)
99
+ res_a = agent_a.send_message(f"{last_msg}")
100
+ history.append({"role": "assistant", "name": "Agent A (Optimist)", "content": res_a.text, "avatar_url": AVATAR_IMAGES["Agent A (Optimist)"]})
101
+ yield history
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
+ res_b = agent_b.send_message(f"Respond to: {res_a.text}")
104
+ history.append({"role": "assistant", "name": "Agent B (Skeptic)", "content": res_b.text, "avatar_url": AVATAR_IMAGES["Agent B (Skeptic)"]})
105
+ last_msg = res_b.text
106
+ yield history
 
107
 
108
+ # --- UI Setup ---
109
+ with gr.Blocks(css=cyberpunk_css, title="AI DEBATE SIMULATOR v2.5") as demo:
110
+ gr.Markdown("# AI DEBATE SIMULATOR v2.5")
111
+ gr.Markdown("## 10-Round AI Debate with Gemini 2.5 Agents")
 
112
 
113
+ topic_btn = gr.Button("🎯 Generate Topics")
114
+ topic_dropdown = gr.Dropdown(label="Choose Topic")
115
+ question_dropdown = gr.Dropdown(label="Choose Starting Question")
116
+ start_btn = gr.Button("🚀 Start Debate")
117
+ chatbox = gr.Chatbot(label="Debate Arena", height=700, avatar_images=AVATAR_IMAGES)
 
 
 
118
 
119
+ state = gr.State()
 
 
 
 
120
 
121
+ topic_btn.click(fn=generate_topics, outputs=topic_dropdown)
122
+ topic_dropdown.change(fn=generate_questions, inputs=topic_dropdown, outputs=question_dropdown)
123
+ start_btn.click(fn=run_debate, inputs=[topic_dropdown, question_dropdown], outputs=chatbox)
 
124
 
 
125
  if __name__ == "__main__":
126
+ demo.launch(debug=True, ssr_mode=False)