Qscar KIM commited on
Commit
d8e9fb3
·
1 Parent(s): 76fc9ad

update codes

Browse files
Files changed (2) hide show
  1. app.py +47 -116
  2. requirements.txt +6 -6
app.py CHANGED
@@ -3,133 +3,57 @@ 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}"
133
  print(f"User logged in: {username}")
134
  else:
135
  print("User not logged in.")
@@ -140,10 +64,12 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
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
 
@@ -211,7 +137,7 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
211
  error_detail = f"Server responded with status {e.response.status_code}."
212
  try:
213
  error_json = e.response.json()
214
- error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
215
  except requests.exceptions.JSONDecodeError:
216
  error_detail += f" Response: {e.response.text[:500]}"
217
  status_message = f"Submission Failed: {error_detail}"
@@ -239,21 +165,26 @@ with gr.Blocks() as demo:
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
-
253
  run_button.click(
254
  fn=run_and_submit_all,
255
  outputs=[status_output, results_table]
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, VisitWebpageTool
 
 
 
8
 
9
  # --- Constants ---
10
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  # --- Basic Agent Definition ---
13
  class BasicAgent:
14
+ def __init__(self, hf_token: str | None = None):
15
+ deepseek_key = os.getenv("DEEPSEEK_API_KEY")
 
 
 
 
 
16
 
17
+ if deepseek_key:
18
+ model = OpenAIModel(
19
+ model_id="deepseek-chat",
20
+ api_base="https://api.deepseek.com",
21
+ api_key=deepseek_key,
22
+ )
23
+ else:
24
+ model = InferenceClientModel(
25
+ model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
26
+ token=hf_token
27
+ )
28
+
29
+ search_tool = DuckDuckGoSearchTool()
30
+ visit_tool = VisitWebpageTool()
31
+
32
+ self.alfred = CodeAgent(
33
+ tools=[search_tool, visit_tool],
34
+ model=model,
35
+ add_base_tools=True,
36
+ planning_interval=3
37
  )
 
38
 
39
  def __call__(self, question: str) -> str:
 
40
  try:
41
+ result = self.alfred.run(question)
 
 
 
 
 
 
 
 
 
 
 
42
  if result is None:
43
  return "unknown"
44
+ return str(result).strip()
 
 
 
 
 
 
45
  except Exception as e:
46
+ print(f"Error during agent runtime execution: {e}")
47
  return "unknown"
48
 
49
+ def run_and_submit_all(profile: gr.OAuthProfile | None, oauth_token: gr.OAuthToken | None = None):
50
+ """
51
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
52
+ and displays the results.
53
+ """
54
  space_id = os.getenv("SPACE_ID")
 
55
  if profile:
56
+ username = f"{profile.username}"
57
  print(f"User logged in: {username}")
58
  else:
59
  print("User not logged in.")
 
64
  submit_url = f"{api_url}/submit"
65
 
66
  try:
67
+ hf_token = oauth_token.token if oauth_token else os.getenv("HF_TOKEN")
68
+ agent = BasicAgent(hf_token=hf_token)
69
  except Exception as e:
70
  print(f"Error instantiating agent: {e}")
71
  return f"Error initializing agent: {e}", None
72
+
73
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
74
  print(agent_code)
75
 
 
137
  error_detail = f"Server responded with status {e.response.status_code}."
138
  try:
139
  error_json = e.response.json()
140
+ error_detail += f" Detail: {error_json.get('detail', error_json.get('message', e.response.text))}"
141
  except requests.exceptions.JSONDecodeError:
142
  error_detail += f" Response: {e.response.text[:500]}"
143
  status_message = f"Submission Failed: {error_detail}"
 
165
  gr.Markdown(
166
  """
167
  **Instructions:**
168
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
169
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
170
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
171
  """
172
  )
 
173
  gr.LoginButton()
174
  run_button = gr.Button("Run Evaluation & Submit All Answers")
175
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
176
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
177
+
178
  run_button.click(
179
  fn=run_and_submit_all,
180
  outputs=[status_output, results_table]
181
  )
182
 
183
  if __name__ == "__main__":
184
+ space_host_startup = os.getenv("SPACE_HOST")
185
+ space_id_startup = os.getenv("SPACE_ID")
186
+ if space_host_startup:
187
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
188
+ if space_id_startup:
189
+ print(f"✅ SPACE_ID found: {space_id_startup}")
190
  demo.launch(debug=True, share=False)
requirements.txt CHANGED
@@ -1,7 +1,7 @@
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.1.0
2
+ duckduckgo-search>=6.2.1
3
+ openai
4
+ markdownify
5
+ pandas
6
+ requests
7
  gradio