hhhhdgfs commited on
Commit
833cf7d
Β·
verified Β·
1 Parent(s): 2517b40

Upload app_gradio.py

Browse files
Files changed (1) hide show
  1. app_gradio.py +294 -0
app_gradio.py ADDED
@@ -0,0 +1,294 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ """
3
+ AI Debate Platform - Gradio version for Hugging Face Spaces
4
+ Full MetaGPT integration
5
+ """
6
+
7
+ import gradio as gr
8
+ import asyncio
9
+ import os
10
+ import sys
11
+
12
+ # Add current directory to path for MetaGPT imports
13
+ sys.path.insert(0, os.path.dirname(__file__))
14
+
15
+ # Configure environment
16
+ os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY", "")
17
+
18
+ # Import debate logic
19
+ try:
20
+ from metagpt.actions import Action
21
+ from metagpt.roles import Role
22
+ from metagpt.schema import Message
23
+ from research_actions import CollectLinks, WebBrowseAndSummarize, ConductResearch
24
+ from metagpt.roles.role import RoleReactMode
25
+ import openai
26
+
27
+ openai.api_key = os.getenv("OPENAI_API_KEY")
28
+ METAGPT_AVAILABLE = True
29
+ except ImportError as e:
30
+ print(f"MetaGPT import failed: {e}")
31
+ METAGPT_AVAILABLE = False
32
+ # Fallback to simple version
33
+ import openai
34
+ from duckduckgo_search import DDGS
35
+ import aiohttp
36
+ from bs4 import BeautifulSoup
37
+
38
+ openai.api_key = os.getenv("OPENAI_API_KEY")
39
+
40
+
41
+ # ===== Debate Logic =====
42
+ if METAGPT_AVAILABLE:
43
+ # Use full MetaGPT version
44
+ class Researcher(Role):
45
+ name: str = "Researcher"
46
+ profile: str = "Research Assistant"
47
+
48
+ def __init__(self, **data):
49
+ super().__init__(**data)
50
+ self.set_actions([CollectLinks, WebBrowseAndSummarize, ConductResearch])
51
+ self._set_react_mode(RoleReactMode.BY_ORDER.value, len(self.actions))
52
+
53
+ async def research_topic(self, topic: str) -> str:
54
+ collect_action = CollectLinks()
55
+ links = await collect_action.run(topic, decomposition_nums=2, url_per_query=2)
56
+
57
+ browse_action = WebBrowseAndSummarize()
58
+ summaries = []
59
+ url_count = 0
60
+ for query, urls in links.items():
61
+ if urls and url_count < 4:
62
+ remaining_urls = 4 - url_count
63
+ limited_urls = urls[:remaining_urls]
64
+ result = await browse_action.run(*limited_urls, query=query)
65
+ summaries.extend(result.values())
66
+ url_count += len(limited_urls)
67
+
68
+ research_action = ConductResearch()
69
+ content = "\n---\n".join(summaries)
70
+ report = await research_action.run(topic, content)
71
+ return report
72
+
73
+ class Debater(Role):
74
+ name: str = ""
75
+ profile: str = ""
76
+ opponent_name1: str = ""
77
+ opponent_name2: str = ""
78
+ research_info: str = ""
79
+
80
+ def __init__(self, **data):
81
+ super().__init__(**data)
82
+ from metagpt.actions import UserRequirement
83
+ class SpeakAloud(Action):
84
+ name: str = "SpeakAloud"
85
+ async def run(self, context: str, name: str, opponent_name1: str, opponent_name2: str,
86
+ idea: str = "", profile: str = "", round_num: int = 1, research_info: str = "") -> str:
87
+ if round_num <= 3:
88
+ instruction = f"Round {round_num}/3: State your {profile} view with evidence"
89
+ else:
90
+ instruction = f"Round {round_num}: Defend and rebut with evidence"
91
+
92
+ prompt = f"""You are {name}, debating: {idea}
93
+ Previous: {context[-1000:]}
94
+ Research: {research_info[:800]}
95
+ {instruction}
96
+ Response:"""
97
+ rsp = await self._aask(prompt)
98
+ return rsp
99
+
100
+ self.set_actions([SpeakAloud])
101
+ self._watch([UserRequirement, SpeakAloud])
102
+
103
+ async def request_research(self, topic: str, researcher):
104
+ from metagpt.actions import Action
105
+ class RequestResearch(Action):
106
+ name: str = "RequestResearch"
107
+ async def run(self, name: str, profile: str, topic: str) -> str:
108
+ prompt = f"You are {name}, a {profile}. What would you research about: {topic}? (1 query)"
109
+ return await self._aask(prompt)
110
+
111
+ request_action = RequestResearch()
112
+ query = await request_action.run(name=self.name, profile=self.profile, topic=topic)
113
+ research_result = await researcher.research_topic(query)
114
+ self.research_info = f"Query: {query}\nResult: {research_result}"
115
+ return research_result
116
+
117
+ else:
118
+ # Simplified fallback
119
+ async def call_gpt(prompt: str) -> str:
120
+ try:
121
+ response = openai.ChatCompletion.create(
122
+ model="gpt-3.5-turbo",
123
+ messages=[{"role": "user", "content": prompt}],
124
+ temperature=0.7,
125
+ max_tokens=800
126
+ )
127
+ return response.choices[0].message.content
128
+ except Exception as e:
129
+ return f"Error: {str(e)}"
130
+
131
+ class Debater:
132
+ def __init__(self, name: str, profile: str, opponent1: str, opponent2: str):
133
+ self.name = name
134
+ self.profile = profile
135
+ self.research_info = ""
136
+
137
+ async def request_research(self, topic: str, researcher=None):
138
+ self.research_info = f"Basic research on: {topic}"
139
+ return self.research_info
140
+
141
+ async def speak(self, topic: str, context: str, round_num: int) -> str:
142
+ prompt = f"You are {self.name} ({self.profile}), debating: {topic}\nRound {round_num}.\nRespond (200 words):"
143
+ return await call_gpt(prompt)
144
+
145
+
146
+ async def run_debate(topic: str, n_rounds: int = 6):
147
+ """Run debate and return formatted results"""
148
+
149
+ if not os.getenv("OPENAI_API_KEY"):
150
+ return "❌ Error: OPENAI_API_KEY not configured", "", ""
151
+
152
+ try:
153
+ # Create debaters
154
+ if METAGPT_AVAILABLE:
155
+ researcher = Researcher()
156
+ principal = Debater(name="Principal", profile="School", opponent_name1="John", opponent_name2="Mom")
157
+ student = Debater(name="John", profile="Student", opponent_name1="Mom", opponent_name2="Principal")
158
+ parent = Debater(name="Mom", profile="Parent", opponent_name1="Principal", opponent_name2="John")
159
+ else:
160
+ principal = Debater("Principal", "School", "John", "Mom")
161
+ student = Debater("John", "Student", "Mom", "Principal")
162
+ parent = Debater("Mom", "Parent", "Principal", "John")
163
+ researcher = None
164
+
165
+ # Research phase
166
+ research_text = "## πŸ” Research Phase\n\n"
167
+ for debater in [principal, student, parent]:
168
+ result = await debater.request_research(topic, researcher)
169
+ research_text += f"**{debater.name}**: {result[:200]}...\n\n"
170
+
171
+ # Debate
172
+ debate_text = "## πŸ—£οΈ Debate\n\n"
173
+ speakers = [principal, student, parent]
174
+ context = ""
175
+
176
+ for round_num in range(min(n_rounds, 6)):
177
+ current = speakers[round_num % 3]
178
+
179
+ if METAGPT_AVAILABLE:
180
+ msg = Message(content=topic, role="user", send_to={current.name}, sent_from="User")
181
+ response = await current.run(msg)
182
+ content = response.content
183
+ else:
184
+ content = await current.speak(topic, context, round_num + 1)
185
+
186
+ debate_text += f"### Round {round_num + 1} - {current.name}\n{content}\n\n---\n\n"
187
+ context += f"\n{current.name}: {content}"
188
+
189
+ # Evaluation
190
+ eval_prompt = f"Summarize this debate and provide recommendations:\n\n{context[-2000:]}"
191
+
192
+ if METAGPT_AVAILABLE:
193
+ from metagpt.actions import Action
194
+ class EvaluateDebate(Action):
195
+ name: str = "EvaluateDebate"
196
+ async def run(self, topic: str, content: str) -> str:
197
+ prompt = f"Evaluate debate on '{topic}':\n{content}\nProvide summary and recommendations:"
198
+ return await self._aask(prompt)
199
+
200
+ evaluator = EvaluateDebate()
201
+ evaluation = await evaluator.run(topic, context)
202
+ else:
203
+ evaluation = await call_gpt(eval_prompt)
204
+
205
+ eval_text = f"## πŸ“‹ Evaluation\n\n{evaluation}"
206
+
207
+ return research_text, debate_text, eval_text
208
+
209
+ except Exception as e:
210
+ return f"❌ Error: {str(e)}", "", ""
211
+
212
+
213
+ def debate_interface(topic: str, rounds: int):
214
+ """Gradio interface wrapper"""
215
+ if not topic:
216
+ return "⚠️ Please enter a debate topic", "", ""
217
+
218
+ try:
219
+ research, debate, evaluation = asyncio.run(run_debate(topic, rounds))
220
+ return research, debate, evaluation
221
+ except Exception as e:
222
+ return f"❌ Error: {str(e)}", "", ""
223
+
224
+
225
+ # ===== Gradio UI =====
226
+ with gr.Blocks(title="AI Debate Platform", theme=gr.themes.Soft()) as demo:
227
+ gr.Markdown("# πŸ—£οΈ AI Debate Platform")
228
+ gr.Markdown("Three AI agents debate different perspectives on school policy topics")
229
+
230
+ # Check API key
231
+ if not os.getenv("OPENAI_API_KEY"):
232
+ gr.Markdown("### ⚠️ Configuration Required")
233
+ gr.Markdown("""
234
+ **For Hugging Face Spaces:**
235
+ 1. Go to Settings β†’ Repository secrets
236
+ 2. Add secret: `OPENAI_API_KEY` = `sk-your-key`
237
+ 3. Restart the Space
238
+
239
+ **For local:**
240
+ ```bash
241
+ export OPENAI_API_KEY="sk-your-key"
242
+ ```
243
+ """)
244
+
245
+ with gr.Row():
246
+ with gr.Column(scale=2):
247
+ topic_input = gr.Textbox(
248
+ label="Debate Topic",
249
+ placeholder="e.g., Should schools ban smartphones?",
250
+ lines=2
251
+ )
252
+ rounds_slider = gr.Slider(
253
+ minimum=3,
254
+ maximum=9,
255
+ value=6,
256
+ step=1,
257
+ label="Number of Rounds"
258
+ )
259
+ submit_btn = gr.Button("Start Debate", variant="primary", size="lg")
260
+
261
+ with gr.Column(scale=1):
262
+ gr.Markdown("### Example Topics")
263
+ gr.Markdown("""
264
+ - Should schools ban smartphones?
265
+ - Is homework necessary?
266
+ - Should school start later?
267
+ - Should uniforms be required?
268
+ """)
269
+
270
+ gr.Markdown("---")
271
+
272
+ with gr.Tabs():
273
+ with gr.Tab("πŸ“‹ Evaluation"):
274
+ eval_output = gr.Markdown(label="Evaluation")
275
+
276
+ with gr.Tab("πŸ—£οΈ Full Debate"):
277
+ debate_output = gr.Markdown(label="Debate Transcript")
278
+
279
+ with gr.Tab("πŸ” Research"):
280
+ research_output = gr.Markdown(label="Research Phase")
281
+
282
+ # Event handler
283
+ submit_btn.click(
284
+ fn=debate_interface,
285
+ inputs=[topic_input, rounds_slider],
286
+ outputs=[research_output, debate_output, eval_output]
287
+ )
288
+
289
+ gr.Markdown("---")
290
+ gr.Markdown("πŸ’‘ **Powered by**: " + ("MetaGPT Framework" if METAGPT_AVAILABLE else "OpenAI API"))
291
+
292
+ # Launch
293
+ if __name__ == "__main__":
294
+ demo.launch()