s1144662 commited on
Commit
2c27ada
·
verified ·
1 Parent(s): 858c148

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +59 -146
app.py CHANGED
@@ -3,210 +3,123 @@ import gradio as gr
3
  import requests
4
  import pandas as pd
5
  from typing import Optional
6
- from smolagents import CodeAgent, DuckDuckGoSearchTool, OpenAIServerModel
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
9
 
10
  class GroqAgent:
11
- """使用 smolagents + Groq API + Search Tool 的 Agent"""
12
  def __init__(self):
13
  self.api_key = os.getenv("GROQ_API_KEY")
14
  if not self.api_key:
15
- print("✗ GROQ_API_KEY not found")
16
  self.agent = None
17
  return
18
 
19
- # 1. 設定模型:使用 OpenAI 相容模式連接 Groq
20
  model = OpenAIServerModel(
21
  model_id="llama-3.3-70b-versatile",
22
  api_base="https://api.groq.com/openai/v1",
23
  api_key=self.api_key
24
  )
25
 
26
- # 2. 建立 Agent:加入搜尋工具 (DuckDuckGoSearchTool)
27
- # 這是拿到 > 30% 分數的關鍵,讓它能上網查資料
28
  self.agent = CodeAgent(
29
- tools=[DuckDuckGoSearchTool()],
30
  model=model,
31
- max_steps=4, # 限制思考步數避免超時
32
  verbosity_level=1
33
  )
34
- print("✓ Groq agent (smolagents) initialized successfully")
35
 
36
  def __call__(self, question: str) -> str:
37
- """回答問題"""
38
  if self.agent is None:
39
  return "Error: GROQ_API_KEY not configured."
40
 
41
  try:
42
- # 增加提示詞,告訴 Agent 如果遇到圖片題該怎麼辦
43
  prompt = f"""
44
- Answer the following question as strictly and concisely as possible.
45
- If the question asks about a specific fact, use the search tool to find it.
46
- If the question refers to an image, video, or audio file that you cannot see:
47
- 1. Try to infer the answer from the text context if possible.
48
- 2. Or search for the specific text descriptions in the question.
49
- 3. If absolutely impossible, make an educated guess.
50
 
51
  Question: {question}
52
  """
53
-
54
- # 執行 Agent
55
- answer = self.agent.run(prompt)
56
- return str(answer)
57
-
58
  except Exception as e:
59
- return f"Error running agent: {str(e)[:150]}"
60
-
61
 
62
  def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
63
- """主要評估和提交函數"""
64
-
65
- # 檢查登入
66
  if profile is None:
67
- return "⚠️ Please click 'Login with Hugging Face' button first!", None
68
 
69
  username = profile.username
70
  space_id = os.getenv("SPACE_ID", "s1144662")
71
  api_url = DEFAULT_API_URL
72
 
73
- # 初始化 Agent
74
  try:
75
  agent_wrapper = GroqAgent()
76
  if agent_wrapper.agent is None:
77
- return "❌ Error: GROQ_API_KEY not found!\n\nPlease add your Groq API key to Secrets.", None
78
  except Exception as e:
79
- return f"❌ Agent initialization failed: {str(e)}", None
80
 
81
- # 獲取問題
82
  try:
83
- print("Fetching questions...")
84
  response = requests.get(f"{api_url}/questions", timeout=30)
85
- response.raise_for_status()
86
- questions_data = response.json()
87
- print(f"✓ Got {len(questions_data)} questions")
88
  except Exception as e:
89
- return f"❌ Failed to fetch questions: {str(e)}", None
90
 
91
- answers_payload = []
92
- results_log = []
93
 
94
- total = len(questions_data)
95
-
96
- # 回答每個問題
97
- for idx, item in enumerate(questions_data, 1):
98
- task_id = item.get("task_id")
99
- question_text = item.get("question")
100
-
101
- print(f"[{idx}/{total}] Processing: {task_id[:8]}...")
102
 
103
- try:
104
- # 呼叫我們的 Agent
105
- answer = agent_wrapper(question_text)
106
-
107
- answers_payload.append({
108
- "task_id": task_id,
109
- "submitted_answer": answer
110
- })
111
-
112
- results_log.append({
113
- "Task ID": task_id[:12] + "...",
114
- "Question": question_text[:70] + "...",
115
- "Answer": str(answer)[:150]
116
- })
117
-
118
- except Exception as e:
119
- error_msg = str(e)[:100]
120
- answers_payload.append({
121
- "task_id": task_id,
122
- "submitted_answer": f"Error: {error_msg}"
123
- })
124
- results_log.append({
125
- "Task ID": task_id,
126
- "Question": question_text[:50],
127
- "Answer": f"Error: {error_msg}"
128
- })
129
 
130
- # 提交答案
131
  try:
132
- print("Submitting answers...")
133
- submission_data = {
134
  "username": username,
135
  "agent_code": f"https://huggingface.co/spaces/{space_id}/tree/main",
136
- "answers": answers_payload
137
- }
138
-
139
- response = requests.post(
140
- f"{api_url}/submit",
141
- json=submission_data,
142
- timeout=120
143
- )
144
- response.raise_for_status()
145
- data = response.json()
146
-
147
  score = data.get('score', 0)
148
- correct = data.get('correct_count', 0)
149
- total_q = data.get('total_attempted', 0)
150
-
151
- print(f"✓ Score: {score}% ({correct}/{total_q})")
152
-
153
- # 生成結果訊息
154
- if score >= 30:
155
- status_msg = f"""🎉 CONGRATULATIONS! YOU PASSED! 🎉
156
-
157
- 📊 Final Score: {score}% ({correct}/{total_q} correct)
158
- ✅ Required: 30% (You exceeded it!)
159
-
160
- 🎓 Next Step: Get Your Certificate
161
- 👉 Visit: https://huggingface.co/spaces/agents-course/Unit4-Final-Certificate
162
-
163
- Great job! 🚀"""
164
- else:
165
- status_msg = f"""📊 Score: {score}% ({correct}/{total_q} correct)
166
- ❌ Required: 30% to pass
167
- 📈 You need {int((30 * total_q / 100) - correct)} more correct answers
168
-
169
- 💡 Tip: Check if the search tool is working correctly."""
170
-
171
- except requests.exceptions.RequestException as e:
172
- status_msg = f"❌ Submission failed (network error): {str(e)[:200]}"
173
  except Exception as e:
174
- status_msg = f" Submission failed: {str(e)[:200]}"
175
 
176
- return status_msg, pd.DataFrame(results_log)
177
-
178
-
179
- # Gradio 介面
180
- with gr.Blocks(title="Unit 4 Final Assignment", theme=gr.themes.Soft()) as demo:
181
- gr.Markdown("""
182
- # 🎓 Unit 4 Final Project: AI Agent (Fixed with smolagents)
183
-
184
- ### Using Groq API (Llama 3.3 70B) + Search Tool
185
- **Goal**: Score ≥ 30% to get certificate
186
- """)
187
-
188
  with gr.Row():
189
- gr.LoginButton(scale=1)
190
- run_btn = gr.Button("🚀 Run Evaluation & Submit All Answers", scale=3, variant="primary")
191
-
192
- gr.Markdown("---")
193
-
194
- status = gr.Textbox(label="📊 Submission Status", lines=8, interactive=False)
195
- details = gr.DataFrame(label="📝 Detailed Results", interactive=False)
196
-
197
- run_btn.click(
198
- fn=run_and_submit_all,
199
- inputs=[],
200
- outputs=[status, details]
201
- )
202
-
203
- gr.Markdown("""
204
- ---
205
- ### 💡 Tips
206
- - Make sure `GROQ_API_KEY` is in Secrets.
207
- - This agent uses DuckDuckGo Search to answer factual questions.
208
- - Image questions might still fail, but text questions should pass!
209
- """)
210
 
211
  if __name__ == "__main__":
212
  demo.launch()
 
3
  import requests
4
  import pandas as pd
5
  from typing import Optional
6
+ from smolagents import CodeAgent, OpenAIServerModel, tool
7
+
8
+ # --- 關鍵修改:手動定義搜尋工具,繞過 smolagents 的檢查錯誤 ---
9
+ try:
10
+ from duckduckgo_search import DDGS
11
+ except ImportError:
12
+ # 萬一真的沒裝到,這邊做最後一道防線
13
+ os.system('pip install duckduckgo-search==6.4.2')
14
+ from duckduckgo_search import DDGS
15
+
16
+ @tool
17
+ def web_search(query: str) -> str:
18
+ """
19
+ Performs a web search to find information about specific facts, events, or data.
20
+
21
+ Args:
22
+ query: The search query string.
23
+ """
24
+ try:
25
+ results = DDGS().text(query, max_results=5)
26
+ return str(results)
27
+ except Exception as e:
28
+ return f"Search error: {str(e)}"
29
+ # -----------------------------------------------------------
30
 
31
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
32
 
33
  class GroqAgent:
 
34
  def __init__(self):
35
  self.api_key = os.getenv("GROQ_API_KEY")
36
  if not self.api_key:
 
37
  self.agent = None
38
  return
39
 
 
40
  model = OpenAIServerModel(
41
  model_id="llama-3.3-70b-versatile",
42
  api_base="https://api.groq.com/openai/v1",
43
  api_key=self.api_key
44
  )
45
 
46
+ # 使用我們手動定義的 web_search 工具
 
47
  self.agent = CodeAgent(
48
+ tools=[web_search],
49
  model=model,
50
+ max_steps=4,
51
  verbosity_level=1
52
  )
 
53
 
54
  def __call__(self, question: str) -> str:
 
55
  if self.agent is None:
56
  return "Error: GROQ_API_KEY not configured."
57
 
58
  try:
 
59
  prompt = f"""
60
+ Answer the question concisely.
61
+ If it's a factual question (dates, names, events), use the 'web_search' tool.
62
+ If it refers to an image/video you can't see, try to infer from the text or search for the description.
 
 
 
63
 
64
  Question: {question}
65
  """
66
+ return str(self.agent.run(prompt))
 
 
 
 
67
  except Exception as e:
68
+ return f"Error: {str(e)[:150]}"
 
69
 
70
  def run_and_submit_all(profile: Optional[gr.OAuthProfile] = None):
 
 
 
71
  if profile is None:
72
+ return "⚠️ Please login first!", None
73
 
74
  username = profile.username
75
  space_id = os.getenv("SPACE_ID", "s1144662")
76
  api_url = DEFAULT_API_URL
77
 
 
78
  try:
79
  agent_wrapper = GroqAgent()
80
  if agent_wrapper.agent is None:
81
+ return "❌ Error: GROQ_API_KEY not found!", None
82
  except Exception as e:
83
+ return f"❌ Init failed: {str(e)}", None
84
 
 
85
  try:
 
86
  response = requests.get(f"{api_url}/questions", timeout=30)
87
+ questions = response.json()
 
 
88
  except Exception as e:
89
+ return f"❌ Fetch failed: {str(e)}", None
90
 
91
+ answers = []
92
+ logs = []
93
 
94
+ for item in questions:
95
+ q = item.get("question")
96
+ tid = item.get("task_id")
97
+ print(f"Processing: {tid}...")
 
 
 
 
98
 
99
+ ans = agent_wrapper(q)
100
+ answers.append({"task_id": tid, "submitted_answer": ans})
101
+ logs.append({"Task": tid, "Q": q[:50], "A": ans[:100]})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
 
103
  try:
104
+ res = requests.post(f"{api_url}/submit", json={
 
105
  "username": username,
106
  "agent_code": f"https://huggingface.co/spaces/{space_id}/tree/main",
107
+ "answers": answers
108
+ })
109
+ data = res.json()
 
 
 
 
 
 
 
 
110
  score = data.get('score', 0)
111
+ return f"Score: {score}%", pd.DataFrame(logs)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  except Exception as e:
113
+ return f"Submit error: {str(e)}", pd.DataFrame(logs)
114
 
115
+ with gr.Blocks(title="Final Agent") as demo:
116
+ gr.Markdown("# 🚀 Final Agent (Custom Tool Version)")
 
 
 
 
 
 
 
 
 
 
117
  with gr.Row():
118
+ gr.LoginButton()
119
+ btn = gr.Button("Run Evaluation", variant="primary")
120
+ out = gr.Textbox(label="Status")
121
+ tab = gr.DataFrame(label="Results")
122
+ btn.click(run_and_submit_all, outputs=[out, tab])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
 
124
  if __name__ == "__main__":
125
  demo.launch()