MADtoBAD commited on
Commit
b016b2b
·
verified ·
1 Parent(s): fc209f6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +144 -261
app.py CHANGED
@@ -3,302 +3,185 @@ import gradio as gr
3
  import requests
4
  import pandas as pd
5
  from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
6
- import logging
7
 
8
- # Настройка логирования
9
- logging.basicConfig(level=logging.INFO)
10
- logger = logging.getLogger(__name__)
11
 
12
- # --- Константы ---
13
- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
14
-
15
- # --- Internet-Enabled Agent Definition ---
16
- class InternetAgent:
17
  def __init__(self):
18
- print("🌐 InternetAgent initializing with web search capabilities...")
19
 
20
- try:
21
- # Используем модель от Hugging Face и инструмент поиска
22
- self.model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")
23
- self.search_tool = DuckDuckGoSearchTool()
24
-
25
- # Создаем агента с доступом к поиску
26
- self.agent = CodeAgent(
27
- tools=[self.search_tool],
28
- model=self.model,
29
- max_steps=6, # Ограничиваем шаги для скорости
30
- add_base_tools=False # Используем только наши инструменты
31
- )
32
- print("✅ InternetAgent initialized successfully with web search")
33
-
34
- except Exception as e:
35
- print(f"❌ Error initializing InternetAgent: {e}")
36
- self.agent = None
37
- # Резервная база знаний на случай ошибки
38
- self.fallback_knowledge = {
39
- "capital of france": "Paris",
40
- "capital of germany": "Berlin",
41
- "capital of uk": "London",
42
- "capital of usa": "Washington D.C.",
43
- "2+2": "4",
44
- "largest planet": "Jupiter",
45
- }
46
 
47
- def __call__(self, question: str) -> str:
48
- print(f"🤖 Processing: {question}")
49
 
50
- if not self.agent:
51
- # Используем резервную базу знаний если агент не инициализирован
52
- question_lower = question.lower()
53
- for key, answer in self.fallback_knowledge.items():
54
- if key in question_lower:
55
- return answer
56
- return "I need internet access to answer this question properly."
57
 
58
- try:
59
- # Создаем оптимизированный промпт для лучших результатов
60
- optimized_prompt = f"""
61
- Please provide a clear, concise, and accurate answer to the following question.
62
- If you need to search for information, use the search tool.
63
- Keep your answer brief and to the point.
64
-
65
- Question: {question}
66
-
67
- Answer:
68
- """
69
-
70
- # Запускаем агента
71
- response = self.agent.run(optimized_prompt)
72
-
73
- # Очищаем ответ
74
- clean_response = self.clean_response(response)
75
- print(f"✅ Answer: {clean_response[:100]}...")
76
-
77
- return clean_response
78
-
79
- except Exception as e:
80
- print(f"❌ Error in agent execution: {e}")
81
- return f"I encountered an error while searching for the answer: {str(e)}"
82
 
83
- def clean_response(self, response: str) -> str:
84
- """Очищает ответ от лишней информации"""
85
- # Удаляем мета-комментарии агента
86
  lines = response.split('\n')
87
  clean_lines = []
88
 
89
  for line in lines:
90
- # Пропускаем строки с инструментами или процессами
91
- if any(term in line.lower() for term in ['tool:', 'searching', 'step', 'using tool']):
92
- continue
93
- # Пропускаем пустые строки в начале
94
- if not clean_lines and not line.strip():
95
  continue
96
- clean_lines.append(line)
 
97
 
98
- clean_response = '\n'.join(clean_lines).strip()
 
99
 
100
- # Если ответ слишком длинный, берем первую часть
101
- if len(clean_response) > 500:
102
- clean_response = clean_response[:497] + "..."
103
 
104
- return clean_response if clean_response else "I couldn't find a clear answer to that question."
105
 
106
- # --- Упрощенная версия для тестирования ---
107
- class LiteInternetAgent:
108
- def __init__(self):
109
- print("🌐 LiteInternetAgent initializing...")
110
- self.search_tool = DuckDuckGoSearchTool()
111
-
112
- def __call__(self, question: str) -> str:
113
- try:
114
- # Прямой поиск через инструмент
115
- result = self.search_tool(question)
116
- return f"According to web search: {result[:300]}..." if len(result) > 300 else result
117
- except Exception as e:
118
- return f"Search failed: {str(e)}"
119
-
120
- # --- Основная функция ---
121
- def run_and_submit_all(profile: gr.OAuthProfile | None):
122
  """
123
- Fetches all questions, runs the InternetAgent on them, submits all answers,
124
- and displays the results.
125
  """
126
- space_id = os.getenv("SPACE_ID")
127
-
128
- if profile:
129
- username = f"{profile.username}"
130
- print(f"User logged in: {username}")
131
- else:
132
- print("User not logged in.")
133
- return "Please Login to Hugging Face with the button.", None
134
-
135
- api_url = DEFAULT_API_URL
136
- questions_url = f"{api_url}/questions"
137
- submit_url = f"{api_url}/submit"
138
-
139
- # 1. Instantiate our Internet Agent
140
- try:
141
- # Пробуем полную версию, если не работает - упрощенную
142
- agent = InternetAgent()
143
- if agent.agent is None:
144
- agent = LiteInternetAgent()
145
- print("✅ InternetAgent created successfully")
146
- except Exception as e:
147
- print(f"Error instantiating agent: {e}")
148
- return f"Error initializing agent: {e}", None
149
 
150
- agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
151
- print(f"Agent code URL: {agent_code}")
152
-
153
- # 2. Fetch Questions
154
- print(f"Fetching questions from: {questions_url}")
155
  try:
156
  response = requests.get(questions_url, timeout=30)
157
- response.raise_for_status()
158
  questions_data = response.json()
159
- if not questions_data:
160
- print("Fetched questions list is empty.")
161
- return "Fetched questions list is empty or invalid format.", None
162
- print(f"✅ Fetched {len(questions_data)} questions.")
163
  except Exception as e:
164
- error_msg = f"Error fetching questions: {e}"
165
- print(error_msg)
166
-
167
- # Демо-режим с разными типами вопросов
168
- demo_questions = [
169
- {"task_id": "demo1", "question": "What is the capital of France?"},
170
- {"task_id": "demo2", "question": "What is the current weather in Tokyo?"},
171
- {"task_id": "demo3", "question": "Who won the Nobel Prize in Physics in 2023?"},
172
- {"task_id": "demo4", "question": "What is the population of Brazil?"},
173
- {"task_id": "demo5", "question": "Explain quantum computing in simple terms"},
174
- ]
175
- questions_data = demo_questions
176
- print("🚨 Using demo questions since API is unavailable")
177
-
178
- # 3. Run your Agent
179
- results_log = []
180
- answers_payload = []
181
- print(f"Running agent on {len(questions_data)} questions...")
182
 
183
- for i, item in enumerate(questions_data):
184
- task_id = item.get("task_id")
185
- question_text = item.get("question")
 
 
 
 
186
 
187
- if not task_id or question_text is None:
188
- print(f"Skipping item with missing task_id or question: {item}")
189
- continue
190
 
191
- print(f"🔍 Processing question {i+1}/{len(questions_data)}: {question_text[:50]}...")
192
-
193
- try:
194
- submitted_answer = agent(question_text)
195
- answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
196
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
197
- except Exception as e:
198
- print(f"❌ Error running agent on task {task_id}: {e}")
199
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
200
-
201
- if not answers_payload:
202
- print("Agent did not produce any answers to submit.")
203
- return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
204
-
205
- # 4. Prepare Submission
206
- submission_data = {
207
- "username": username.strip(),
208
- "agent_code": agent_code,
209
- "answers": answers_payload
210
- }
211
-
212
- status_update = f"✅ Agent finished. Processed {len(answers_payload)} answers for user '{username}'"
213
- print(status_update)
214
-
215
- # 5. Submit answers (только если вопросы реальные, не демо)
216
- if "demo" not in str(questions_data[0].get("task_id", "")):
217
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
218
- try:
219
- response = requests.post(submit_url, json=submission_data, timeout=120)
220
- response.raise_for_status()
221
- result_data = response.json()
222
 
223
- final_status = (
224
- f"🎉 Submission Successful!\n"
225
- f"👤 User: {result_data.get('username')}\n"
226
- f"📊 Overall Score: {result_data.get('score', 'N/A')}% "
227
- f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
228
- f"💬 Message: {result_data.get('message', 'No message received.')}"
229
- )
230
- print("✅ Submission successful.")
231
- results_df = pd.DataFrame(results_log)
232
- return final_status, results_df
233
 
234
- except Exception as e:
235
- error_message = f"❌ Submission Failed: {str(e)}"
236
- print(error_message)
237
- results_df = pd.DataFrame(results_log)
238
- return error_message, results_df
239
- else:
240
- # Демо-режим: показываем ответы но не отправляем
241
- demo_status = (
242
- f"🧪 DEMO MODE (API Unavailable)\n"
243
- f"👤 User: {username}\n"
244
- f"📊 Processed: {len(answers_payload)} demo questions\n"
245
- f"🌐 Agent used web search for answers\n"
246
- f"💬 Real submission disabled - API not accessible\n\n"
247
- f"Check the web-powered answers below!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  )
249
- print("✅ Demo completed - showing results without submission")
250
- results_df = pd.DataFrame(results_log)
251
- return demo_status, results_df
252
-
253
- # --- Gradio Interface ---
254
- with gr.Blocks(title="Internet-Enabled AI Agent") as demo:
255
- gr.Markdown("""
256
- # 🌐 Internet-Enabled AI Agent
257
- **Powered by web search and large language models**
 
 
 
 
258
 
259
- ### 🔧 Capabilities:
260
- - **Web Search**: Real-time information from DuckDuckGo
261
- - **LLM Power**: Qwen2.5-32B model for understanding
262
- - **Multi-step Reasoning**: Complex question answering
263
 
264
- ### 📚 Example questions:
265
- - *"Current weather in any city"*
266
- - *"Latest news headlines"*
267
- - *"Historical facts and data"*
268
- - *"Scientific explanations"*
269
- - *"Complex calculations"*
270
- """)
271
 
272
- gr.Markdown("""
273
- ### ⚠️ Important Notes:
274
- - This agent requires internet access
275
- - Responses may take longer due to web searches
276
- - Some questions might not have clear online answers
277
- """)
278
 
279
- with gr.Row():
280
- with gr.Column():
281
- gr.LoginButton()
282
- run_button = gr.Button("🚀 Run Evaluation", variant="primary")
 
283
 
284
- with gr.Row():
285
- with gr.Column():
286
- status_output = gr.Textbox(
287
- label="Status",
288
- lines=4,
289
- interactive=False
290
- )
291
- with gr.Column():
292
- results_table = gr.DataFrame(
293
- label="Questions & Answers",
294
- wrap=True
295
- )
296
-
297
- run_button.click(
298
- fn=run_and_submit_all,
299
- outputs=[status_output, results_table]
300
  )
301
 
 
302
  if __name__ == "__main__":
303
- print("🚀 Starting Internet-Enabled AI Agent...")
304
- demo.launch(debug=True, share=False)
 
3
  import requests
4
  import pandas as pd
5
  from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
 
6
 
7
+ # Адрес API системы оценки
8
+ API_URL = "https://agents-course-unit4-scoring.hf.space"
 
9
 
10
+ class WebSearchAgent:
 
 
 
 
11
  def __init__(self):
12
+ print("Starting web search agent...")
13
 
14
+ # Используем модель от Hugging Face
15
+ model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")
16
+
17
+ # Инструмент для поиска в интернете через DuckDuckGo
18
+ search_tool = DuckDuckGoSearchTool()
19
+
20
+ # Создаем агента который умеет искать в интернете
21
+ self.agent = CodeAgent(
22
+ tools=[search_tool],
23
+ model=model,
24
+ max_steps=4
25
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
+ def answer_question(self, question):
28
+ print(f"Question: {question}")
29
 
30
+ # Промпт для агента - инструкция как отвечать
31
+ prompt = f"""
32
+ Answer this question clearly and accurately:
33
+ {question}
 
 
 
34
 
35
+ If you need to search for information, use the search tool.
36
+ Keep the answer concise.
37
+ """
38
+
39
+ # Запускаем агента для получения ответа
40
+ response = self.agent.run(prompt)
41
+
42
+ # Убираем лишние технические детали из ответа
43
+ clean_answer = self.clean_response(response)
44
+ print(f"Answer: {clean_answer[:100]}")
45
+
46
+ return clean_answer
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ def clean_response(self, response):
49
+ # Разбиваем ответ на строки
 
50
  lines = response.split('\n')
51
  clean_lines = []
52
 
53
  for line in lines:
54
+ # Пропускаем строки про инструменты и процесс поиска
55
+ if any(word in line.lower() for word in ['tool:', 'searching', 'step']):
 
 
 
56
  continue
57
+ if line.strip(): # Добавляем только непустые строки
58
+ clean_lines.append(line)
59
 
60
+ # Собираем обратно в текст
61
+ result = '\n'.join(clean_lines).strip()
62
 
63
+ # Если ответ слишком длинный, обрезаем
64
+ if len(result) > 400:
65
+ result = result[:397] + "..."
66
 
67
+ return result if result else "Could not find answer"
68
 
69
+ def run_evaluation(profile):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  """
71
+ Главная функция которая запускает весь процесс оценки
 
72
  """
73
+ # Проверяем что пользователь вошел в систему
74
+ if not profile:
75
+ return "Please login first.", None
76
+
77
+ username = profile.username
78
+ print(f"User: {username}")
79
+
80
+ # Создаем агента для поиска в интернете
81
+ agent = WebSearchAgent()
82
+
83
+ # Получаем вопросы с API системы оценки
84
+ questions_url = f"{API_URL}/questions"
 
 
 
 
 
 
 
 
 
 
 
85
 
 
 
 
 
 
86
  try:
87
  response = requests.get(questions_url, timeout=30)
 
88
  questions_data = response.json()
89
+ print(f"Received {len(questions_data)} questions")
 
 
 
90
  except Exception as e:
91
+ print(f"Error getting questions: {e}")
92
+ return f"Cannot get questions: {e}", None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
 
94
+ # Обрабатываем каждый вопрос
95
+ results_list = []
96
+ answers_for_submission = []
97
+
98
+ for i, question_item in enumerate(questions_data):
99
+ task_id = question_item.get("task_id")
100
+ question_text = question_item.get("question")
101
 
102
+ if task_id and question_text:
103
+ print(f"Processing question {i+1}")
 
104
 
105
+ # Получаем ответ от агента
106
+ answer = agent.answer_question(question_text)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
 
108
+ # Сохраняем для отправки
109
+ answers_for_submission.append({
110
+ "task_id": task_id,
111
+ "submitted_answer": answer
112
+ })
 
 
 
 
 
113
 
114
+ # Сохраняем для показа в таблице
115
+ results_list.append({
116
+ "Task ID": task_id,
117
+ "Question": question_text,
118
+ "Answer": answer
119
+ })
120
+
121
+ # Подготавливаем данные для отправки
122
+ space_id = os.getenv("SPACE_ID")
123
+ agent_code_url = f"https://huggingface.co/spaces/{space_id}"
124
+
125
+ data_to_send = {
126
+ "username": username,
127
+ "agent_code": agent_code_url,
128
+ "answers": answers_for_submission
129
+ }
130
+
131
+ # Отправляем ответы на проверку
132
+ submit_url = f"{API_URL}/submit"
133
+
134
+ try:
135
+ response = requests.post(submit_url, json=data_to_send, timeout=120)
136
+ result_data = response.json()
137
+
138
+ # Формируем итоговый статус
139
+ status_text = (
140
+ f"Evaluation completed\n"
141
+ f"User: {result_data.get('username')}\n"
142
+ f"Score: {result_data.get('score', 'N/A')}%\n"
143
+ f"Correct answers: {result_data.get('correct_count', '?')}\n"
144
+ f"Message: {result_data.get('message', 'No message')}"
145
  )
146
+
147
+ results_table = pd.DataFrame(results_list)
148
+ return status_text, results_table
149
+
150
+ except Exception as e:
151
+ error_text = f"Submission error: {e}"
152
+ results_table = pd.DataFrame(results_list)
153
+ return error_text, results_table
154
+
155
+ # Создаем веб-интерфейс
156
+ with gr.Blocks() as web_interface:
157
+ gr.Markdown("# AI Agent with Web Search")
158
+ gr.Markdown("This agent can search the internet to answer questions.")
159
 
160
+ # Кнопка для входа в систему
161
+ login_btn = gr.LoginButton()
 
 
162
 
163
+ # Кнопка для запуска оценки
164
+ run_btn = gr.Button("Start Evaluation")
 
 
 
 
 
165
 
166
+ # Поле для вывода статуса
167
+ status_display = gr.Textbox(
168
+ label="Status",
169
+ lines=4,
170
+ interactive=False
171
+ )
172
 
173
+ # Таблица для результатов
174
+ results_display = gr.DataFrame(
175
+ label="Questions and Answers",
176
+ wrap=True
177
+ )
178
 
179
+ # Обработчик нажатия кнопки
180
+ run_btn.click(
181
+ fn=run_evaluation,
182
+ outputs=[status_display, results_display]
 
 
 
 
 
 
 
 
 
 
 
 
183
  )
184
 
185
+ # Запускаем приложение
186
  if __name__ == "__main__":
187
+ web_interface.launch()