Qscar KIM commited on
Commit
1e1443b
·
1 Parent(s): 6633677

update codes

Browse files
Files changed (2) hide show
  1. app.py +69 -109
  2. requirements.txt +4 -5
app.py CHANGED
@@ -3,130 +3,61 @@ import gradio as gr
3
  import requests
4
  import inspect
5
  import pandas as pd
6
- import time
7
- import re
8
- from bs4 import BeautifulSoup
9
-
10
- from smolagents import CodeAgent, InferenceClientModel, Tool
11
 
12
  # --- Constants ---
13
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
14
 
15
- # --- High-Performance Tool 1: 다차원 구조화 웹 검색 툴 ---
16
- class AdvancedSearchTool(Tool):
17
- name = "web_search"
18
- description = "Executes a deep web search via DuckDuckGo HTML architecture and extracts exact URLs and targeted meta-snippets."
19
- inputs = {"query": {"type": "string", "description": "The precise keyword query to search for"}}
20
- output_type = "string"
21
-
22
- def forward(self, query: str) -> str:
23
- try:
24
- url = f"https://html.duckduckgo.com/html/?q={requests.utils.quote(query)}"
25
- headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
26
- response = requests.get(url, headers=headers, timeout=12)
27
- if response.status_code != 200:
28
- return f"Search Gateway Error: HTTP {response.status_code}"
29
-
30
- soup = BeautifulSoup(response.text, "lxml")
31
- results = []
32
- for i, item in enumerate(soup.select(".result__body")[:5]):
33
- title_anchor = item.select_one(".result__title a")
34
- snippet_div = item.select_one(".result__snippet")
35
- if title_anchor and snippet_div:
36
- title = title_anchor.get_text(strip=True)
37
- link = title_anchor.get("href")
38
- # 내부 리다이렉트 URL 정제
39
- if "uddg=" in link:
40
- link = requests.utils.unquote(link.split("uddg=")[1].split("&")[0])
41
- snippet = snippet_div.get_text(strip=True)
42
- results.append(f"[{i+1}] Title: {title}\nURL: {link}\nContext: {snippet}")
43
- return "\n\n".join(results) if results else "No indexing data found."
44
- except Exception as e:
45
- return f"Search Engine Exception: {str(e)}"
46
-
47
- # --- High-Performance Tool 2: 마크다운 변환형 웹 및 도큐먼트 파서 툴 ---
48
- class DeepPageVisitTool(Tool):
49
- name = "visit_webpage"
50
- description = "Visits a specific URL, bypasses layout boilerplate, and converts raw HTML into a dense Markdown/Table format for complex data analysis."
51
- inputs = {"url": {"type": "string", "description": "The target exact URL to scrape content from"}}
52
- output_type = "string"
53
-
54
- def forward(self, url: str) -> str:
55
- try:
56
- headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36"}
57
- response = requests.get(url, headers=headers, timeout=15)
58
- if response.status_code != 200:
59
- return f"HTTP Access Failure: Status {response.status_code}"
60
-
61
- soup = BeautifulSoup(response.text, "lxml")
62
- # 노이즈 태그 전량 제거
63
- for element in soup(["script", "style", "nav", "footer", "header", "aside"]):
64
- element.extract()
65
-
66
- # GAIA 핵심 지표인 '표 데이터' 보존 처리
67
- for table in soup.find_all("table"):
68
- markdown_table = []
69
- for row in table.find_all("tr"):
70
- cells = [f" {cell.get_text(strip=True)} " for cell in row.find_all(["td", "th"])]
71
- markdown_table.append("|" + "|".join(cells) + "|")
72
- if markdown_table:
73
- table.replace_with(soup.new_string("\n" + "\n".join(markdown_table) + "\n"))
74
-
75
- text = soup.get_text(separator="\n")
76
- text = re.sub(r'\n+', '\n', text).strip()
77
- return text[:6000] # 컨텍스트 상한치 확보
78
- except Exception as e:
79
- return f"Page Scraping Exception: {str(e)}"
80
-
81
  # --- Basic Agent Definition ---
 
82
  class BasicAgent:
83
  def __init__(self):
84
- self.model = InferenceClientModel(
85
- model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
86
- token=os.getenv("HF_TOKEN")
87
- )
88
- self.search_tool = AdvancedSearchTool()
89
- self.visit_tool = DeepPageVisitTool()
90
 
91
- # 가드레일 강화를 위해 verbosity_level을 높이고 복합 연산 지시 프롬프트 템플릿 조정
92
- self.agent = CodeAgent(
93
- tools=[self.search_tool, self.visit_tool],
94
- model=self.model,
95
- max_steps=12,
96
- verbosity_level=2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  )
98
- print("BasicAgent: Guardrail & Self-Correction Engine Loaded.")
99
 
100
  def __call__(self, question: str) -> str:
101
- print(f"Agent received question (first 50 chars): {question[:50]}...")
102
  try:
103
- # 에이전트가 단발성 판단을 내리지 않고 명확한 실행 계획(Execution Plan)을 세우도록 강제하는 엔지니어링 프롬프트
104
- structured_prompt = (
105
- f"You are an expert AI agent solving a GAIA task.\n"
106
- f"Task: {question}\n\n"
107
- f"Strict Protocol:\n"
108
- f"1. Plan: Break down the research and computation into clear sub-tasks.\n"
109
- f"2. Action: Use your code interpreter or tools to gather and verify facts.\n"
110
- f"3. Self-Correction: If any code execution fails with a Traceback, analyze the error, rewrite the script, and run it again.\n"
111
- f"4. Output: Extract the absolute raw answer value (e.g., specific number, name, date) without any markdown formatting wrappers or conversational text. Present this on the very last line."
112
- )
113
-
114
- result = self.agent.run(structured_prompt)
115
  if result is None:
116
  return "unknown"
117
-
118
- # 정답 유실 방지를 위한 최종 타겟 파싱 가드레일 처리
119
- final_output = str(result).strip()
120
- if "\n" in final_output:
121
- final_output = final_output.split("\n")[-1].replace("Final Answer:", "").strip()
122
- return final_output
123
-
124
  except Exception as e:
125
- print(f"Critical System Failure during agent execution: {e}")
126
  return "unknown"
127
 
128
  def run_and_submit_all( profile: gr.OAuthProfile | None):
129
- space_id = os.getenv("SPACE_ID")
 
 
 
 
 
130
 
131
  if profile:
132
  username= f"{profile.username}"
@@ -139,14 +70,17 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
139
  questions_url = f"{api_url}/questions"
140
  submit_url = f"{api_url}/submit"
141
 
 
142
  try:
143
  agent = BasicAgent()
144
  except Exception as e:
145
  print(f"Error instantiating agent: {e}")
146
  return f"Error initializing agent: {e}", None
 
147
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
148
  print(agent_code)
149
 
 
150
  print(f"Fetching questions from: {questions_url}")
151
  try:
152
  response = requests.get(questions_url, timeout=15)
@@ -167,6 +101,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
167
  print(f"An unexpected error occurred fetching questions: {e}")
168
  return f"An unexpected error occurred fetching questions: {e}", None
169
 
 
170
  results_log = []
171
  answers_payload = []
172
  print(f"Running agent on {len(questions_data)} questions...")
@@ -188,10 +123,12 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
188
  print("Agent did not produce any answers to submit.")
189
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
190
 
 
191
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
192
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
193
  print(status_update)
194
 
 
195
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
196
  try:
197
  response = requests.post(submit_url, json=submission_data, timeout=60)
@@ -234,19 +171,22 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
234
  results_df = pd.DataFrame(results_log)
235
  return status_message, results_df
236
 
 
237
  with gr.Blocks() as demo:
238
  gr.Markdown("# Basic Agent Evaluation Runner")
239
  gr.Markdown(
240
  """
241
  **Instructions:**
242
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
243
- 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
244
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
245
  """
246
  )
247
 
248
  gr.LoginButton()
 
249
  run_button = gr.Button("Run Evaluation & Submit All Answers")
 
250
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
251
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
252
 
@@ -256,4 +196,24 @@ with gr.Blocks() as demo:
256
  )
257
 
258
  if __name__ == "__main__":
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  demo.launch(debug=True, share=False)
 
3
  import requests
4
  import inspect
5
  import pandas as pd
6
+ import random
7
+ from smolagents import CodeAgent, InferenceClientModel, OpenAIModel, DuckDuckGoSearchTool
 
 
 
8
 
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # --- Basic Agent Definition ---
13
+ # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
14
  class BasicAgent:
15
  def __init__(self):
16
+ deepseek_key = os.getenv("DEEPSEEK_API_KEY")
17
+ hf_token = os.getenv("HF_TOKEN")
 
 
 
 
18
 
19
+ # 고성능 추론엔진인 DeepSeek API 우선 바인딩, 키 누락 시 무료 인퍼런스 서버리스로 폴백 조치
20
+ if deepseek_key:
21
+ model = OpenAIModel(
22
+ model_id="deepseek-chat",
23
+ api_base="https://api.deepseek.com",
24
+ api_key=deepseek_key,
25
+ )
26
+ print("BasicAgent: Initialized with DeepSeek API Engine.")
27
+ else:
28
+ model = InferenceClientModel(
29
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
30
+ token=hf_token
31
+ )
32
+ print("BasicAgent: DeepSeek Key not found. Falling back to Hugging Face Inference API.")
33
+
34
+ search_tool = DuckDuckGoSearchTool()
35
+
36
+ # 35점 베이스라인의 다단계 계획 수립(Planning Loop) 및 기본 인터프리터 툴 에코시스템 이식
37
+ self.alfred = CodeAgent(
38
+ tools=[search_tool],
39
+ model=model,
40
+ add_base_tools=True,
41
+ planning_interval=3
42
  )
 
43
 
44
  def __call__(self, question: str) -> str:
 
45
  try:
46
+ result = self.alfred.run(question)
 
 
 
 
 
 
 
 
 
 
 
47
  if result is None:
48
  return "unknown"
49
+ return str(result).strip()
 
 
 
 
 
 
50
  except Exception as e:
51
+ print(f"Error during agent runtime execution: {e}")
52
  return "unknown"
53
 
54
  def run_and_submit_all( profile: gr.OAuthProfile | None):
55
+ """
56
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
57
+ and displays the results.
58
+ """
59
+ # --- Determine HF Space Runtime URL and Repo URL ---
60
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
61
 
62
  if profile:
63
  username= f"{profile.username}"
 
70
  questions_url = f"{api_url}/questions"
71
  submit_url = f"{api_url}/submit"
72
 
73
+ # 1. Instantiate Agent ( modify this part to create your agent)
74
  try:
75
  agent = BasicAgent()
76
  except Exception as e:
77
  print(f"Error instantiating agent: {e}")
78
  return f"Error initializing agent: {e}", None
79
+ # In the case of an app running as a hugging Face space, this link points toward your codebase ( usefull for others so please keep it public)
80
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
81
  print(agent_code)
82
 
83
+ # 2. Fetch Questions
84
  print(f"Fetching questions from: {questions_url}")
85
  try:
86
  response = requests.get(questions_url, timeout=15)
 
101
  print(f"An unexpected error occurred fetching questions: {e}")
102
  return f"An unexpected error occurred fetching questions: {e}", None
103
 
104
+ # 3. Run your Agent
105
  results_log = []
106
  answers_payload = []
107
  print(f"Running agent on {len(questions_data)} questions...")
 
123
  print("Agent did not produce any answers to submit.")
124
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
125
 
126
+ # 4. Prepare Submission
127
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
128
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
129
  print(status_update)
130
 
131
+ # 5. Submit
132
  print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
133
  try:
134
  response = requests.post(submit_url, json=submission_data, timeout=60)
 
171
  results_df = pd.DataFrame(results_log)
172
  return status_message, results_df
173
 
174
+ # --- Build Gradio Interface using Blocks ---
175
  with gr.Blocks() as demo:
176
  gr.Markdown("# Basic Agent Evaluation Runner")
177
  gr.Markdown(
178
  """
179
  **Instructions:**
180
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
181
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
182
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
183
  """
184
  )
185
 
186
  gr.LoginButton()
187
+
188
  run_button = gr.Button("Run Evaluation & Submit All Answers")
189
+
190
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
191
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
192
 
 
196
  )
197
 
198
  if __name__ == "__main__":
199
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
200
+ space_host_startup = os.getenv("SPACE_HOST")
201
+ space_id_startup = os.getenv("SPACE_ID")
202
+
203
+ if space_host_startup:
204
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
205
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
206
+ else:
207
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
208
+
209
+ if space_id_startup:
210
+ print(f"✅ SPACE_ID found: {space_id_startup}")
211
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
212
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
213
+ else:
214
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
215
+
216
+ print("-"*(60 + len(" App Starting ")) + "\n")
217
+
218
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
219
  demo.launch(debug=True, share=False)
requirements.txt CHANGED
@@ -1,7 +1,6 @@
1
  smolagents>=1.0.0
2
- beautifulsoup4>=4.12.0
3
- lxml>=5.1.0
4
- pandas>=2.0.0
5
- openpyxl>=3.1.0
6
- requests>=2.31.0
7
  gradio
 
1
  smolagents>=1.0.0
2
+ duckduckgo-search>=6.2.1
3
+ openai
4
+ pandas
5
+ requests
 
6
  gradio