MADtoBAD's picture
Update app.py
6be76b8 verified
import os
import gradio as gr
import requests
import pandas as pd
from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel
import logging
# Настройка логирования
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# --- Константы ---
DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
# --- Internet-Enabled Agent Definition ---
class InternetAgent:
def __init__(self):
print("🌐 InternetAgent initializing with web search capabilities...")
try:
# Используем модель от Hugging Face и инструмент поиска
self.model = HfApiModel("Qwen/Qwen2.5-Coder-32B-Instruct")
self.search_tool = DuckDuckGoSearchTool()
# Создаем агента с доступом к поиску
self.agent = CodeAgent(
tools=[self.search_tool],
model=self.model,
max_steps=6, # Ограничиваем шаги для скорости
add_base_tools=False # Используем только наши инструменты
)
print("✅ InternetAgent initialized successfully with web search")
except Exception as e:
print(f"❌ Error initializing InternetAgent: {e}")
self.agent = None
# Резервная база знаний на случай ошибки
self.fallback_knowledge = {
"capital of france": "Paris",
"capital of germany": "Berlin",
"capital of uk": "London",
"capital of usa": "Washington D.C.",
"2+2": "4",
"largest planet": "Jupiter",
}
def __call__(self, question: str) -> str:
print(f"🤖 Processing: {question}")
if not self.agent:
# Используем резервную базу знаний если агент не инициализирован
question_lower = question.lower()
for key, answer in self.fallback_knowledge.items():
if key in question_lower:
return answer
return "I need internet access to answer this question properly."
try:
# Создаем оптимизированный промпт для лучших результатов
optimized_prompt = f"""
Please provide a clear, concise, and accurate answer to the following question.
If you need to search for information, use the search tool.
Keep your answer brief and to the point.
Question: {question}
Answer:
"""
# Запускаем агента
response = self.agent.run(optimized_prompt)
# Очищаем ответ
clean_response = self.clean_response(response)
print(f"✅ Answer: {clean_response[:100]}...")
return clean_response
except Exception as e:
print(f"❌ Error in agent execution: {e}")
return f"I encountered an error while searching for the answer: {str(e)}"
def clean_response(self, response: str) -> str:
"""Очищает ответ от лишней информации"""
# Удаляем мета-комментарии агента
lines = response.split('\n')
clean_lines = []
for line in lines:
# Пропускаем строки с инструментами или процессами
if any(term in line.lower() for term in ['tool:', 'searching', 'step', 'using tool']):
continue
# Пропускаем пустые строки в начале
if not clean_lines and not line.strip():
continue
clean_lines.append(line)
clean_response = '\n'.join(clean_lines).strip()
# Если ответ слишком длинный, берем первую часть
if len(clean_response) > 500:
clean_response = clean_response[:497] + "..."
return clean_response if clean_response else "I couldn't find a clear answer to that question."
# --- Упрощенная версия для тестирования ---
class LiteInternetAgent:
def __init__(self):
print("🌐 LiteInternetAgent initializing...")
self.search_tool = DuckDuckGoSearchTool()
def __call__(self, question: str) -> str:
try:
# Прямой поиск через инструмент
result = self.search_tool(question)
return f"According to web search: {result[:300]}..." if len(result) > 300 else result
except Exception as e:
return f"Search failed: {str(e)}"
# --- Основная функция ---
def run_and_submit_all(profile: gr.OAuthProfile | None):
"""
Fetches all questions, runs the InternetAgent on them, submits all answers,
and displays the results.
"""
space_id = os.getenv("SPACE_ID")
if profile:
username = f"{profile.username}"
print(f"User logged in: {username}")
else:
print("User not logged in.")
return "Please Login to Hugging Face with the button.", None
api_url = DEFAULT_API_URL
questions_url = f"{api_url}/questions"
submit_url = f"{api_url}/submit"
# 1. Instantiate our Internet Agent
try:
# Пробуем полную версию, если не работает - упрощенную
agent = InternetAgent()
if agent.agent is None:
agent = LiteInternetAgent()
print("✅ InternetAgent created successfully")
except Exception as e:
print(f"Error instantiating agent: {e}")
return f"Error initializing agent: {e}", None
agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
print(f"Agent code URL: {agent_code}")
# 2. Fetch Questions
print(f"Fetching questions from: {questions_url}")
try:
response = requests.get(questions_url, timeout=30)
response.raise_for_status()
questions_data = response.json()
if not questions_data:
print("Fetched questions list is empty.")
return "Fetched questions list is empty or invalid format.", None
print(f"✅ Fetched {len(questions_data)} questions.")
except Exception as e:
error_msg = f"❌ Error fetching questions: {e}"
print(error_msg)
# Демо-режим с разными типами вопросов
demo_questions = [
{"task_id": "demo1", "question": "What is the capital of France?"},
{"task_id": "demo2", "question": "What is the current weather in Tokyo?"},
{"task_id": "demo3", "question": "Who won the Nobel Prize in Physics in 2023?"},
{"task_id": "demo4", "question": "What is the population of Brazil?"},
{"task_id": "demo5", "question": "Explain quantum computing in simple terms"},
]
questions_data = demo_questions
print("🚨 Using demo questions since API is unavailable")
# 3. Run your Agent
results_log = []
answers_payload = []
print(f"Running agent on {len(questions_data)} questions...")
for i, item in enumerate(questions_data):
task_id = item.get("task_id")
question_text = item.get("question")
if not task_id or question_text is None:
print(f"Skipping item with missing task_id or question: {item}")
continue
print(f"🔍 Processing question {i+1}/{len(questions_data)}: {question_text[:50]}...")
try:
submitted_answer = agent(question_text)
answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
except Exception as e:
print(f"❌ Error running agent on task {task_id}: {e}")
results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
if not answers_payload:
print("Agent did not produce any answers to submit.")
return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
# 4. Prepare Submission
submission_data = {
"username": username.strip(),
"agent_code": agent_code,
"answers": answers_payload
}
status_update = f"✅ Agent finished. Processed {len(answers_payload)} answers for user '{username}'"
print(status_update)
# 5. Submit answers (только если вопросы реальные, не демо)
if "demo" not in str(questions_data[0].get("task_id", "")):
print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
try:
response = requests.post(submit_url, json=submission_data, timeout=120)
response.raise_for_status()
result_data = response.json()
final_status = (
f"🎉 Submission Successful!\n"
f"👤 User: {result_data.get('username')}\n"
f"📊 Overall Score: {result_data.get('score', 'N/A')}% "
f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
f"💬 Message: {result_data.get('message', 'No message received.')}"
)
print("✅ Submission successful.")
results_df = pd.DataFrame(results_log)
return final_status, results_df
except Exception as e:
error_message = f"❌ Submission Failed: {str(e)}"
print(error_message)
results_df = pd.DataFrame(results_log)
return error_message, results_df
else:
# Демо-режим: показываем ответы но не отправляем
demo_status = (
f"🧪 DEMO MODE (API Unavailable)\n"
f"👤 User: {username}\n"
f"📊 Processed: {len(answers_payload)} demo questions\n"
f"🌐 Agent used web search for answers\n"
f"💬 Real submission disabled - API not accessible\n\n"
f"Check the web-powered answers below!"
)
print("✅ Demo completed - showing results without submission")
results_df = pd.DataFrame(results_log)
return demo_status, results_df
# --- Gradio Interface ---
with gr.Blocks(title="Internet-Enabled AI Agent") as demo:
gr.Markdown("""
# 🌐 Internet-Enabled AI Agent
**Powered by web search and large language models**
### 🔧 Capabilities:
- **Web Search**: Real-time information from DuckDuckGo
- **LLM Power**: Qwen2.5-32B model for understanding
- **Multi-step Reasoning**: Complex question answering
### 📚 Example questions:
- *"Current weather in any city"*
- *"Latest news headlines"*
- *"Historical facts and data"*
- *"Scientific explanations"*
- *"Complex calculations"*
""")
gr.Markdown("""
### ⚠️ Important Notes:
- This agent requires internet access
- Responses may take longer due to web searches
- Some questions might not have clear online answers
""")
with gr.Row():
with gr.Column():
gr.LoginButton()
run_button = gr.Button("🚀 Run Evaluation", variant="primary")
with gr.Row():
with gr.Column():
status_output = gr.Textbox(
label="Status",
lines=4,
interactive=False
)
with gr.Column():
results_table = gr.DataFrame(
label="Questions & Answers",
wrap=True
)
run_button.click(
fn=run_and_submit_all,
outputs=[status_output, results_table]
)
if __name__ == "__main__":
print("🚀 Starting Internet-Enabled AI Agent...")
demo.launch(debug=True, share=False)