LamiaYT commited on
Commit
675eb1d
·
1 Parent(s): c6061a5
Files changed (2) hide show
  1. app.py +1 -1
  2. txt.txt +1 -383
app.py CHANGED
@@ -21,7 +21,7 @@ class WebSearchEngine:
21
  })
22
 
23
  # API Keys (set these in environment variables)
24
- self.serper_api_key = os.getenv("90f426e61bed9f1ffce51a95b98945531c35279a") # Get from serper.dev
25
  self.brave_api_key = os.getenv("BRAVE_API_KEY") # Get from brave.com/search/api
26
  self.serpapi_key = os.getenv("SERPAPI_KEY") # Get from serpapi.com
27
 
 
21
  })
22
 
23
  # API Keys (set these in environment variables)
24
+ self.serper_api_key = os.getenv("SERPER_API_KEY") # Get from serper.dev
25
  self.brave_api_key = os.getenv("BRAVE_API_KEY") # Get from brave.com/search/api
26
  self.serpapi_key = os.getenv("SERPAPI_KEY") # Get from serpapi.com
27
 
txt.txt CHANGED
@@ -1,383 +1 @@
1
- llama-index-core
2
- llama-index-llms-huggingface
3
- transformers>=4.30.0
4
- torch>=2.0.0
5
- accelerate
6
- gradio>=4.0.0
7
- requests
8
- pandas
9
- python-dotenv
10
- duckduckgo-search
11
- sympy
12
- sentencepiece
13
- protobuf
14
-
15
- app.py
16
- # app.py
17
- from llama_index.llms.huggingface import HuggingFaceLLM
18
- from llama_index.core.agent import ReActAgent
19
- from llama_index.core.tools import FunctionTool
20
- from transformers import AutoTokenizer
21
- import os
22
- import gradio as gr
23
- import requests
24
- import pandas as pd
25
- import traceback
26
-
27
- # Import real tool dependencies
28
- try:
29
- from duckduckgo_search import DDGS
30
- except ImportError:
31
- print("Warning: duckduckgo_search not installed. Web search will be limited.")
32
- DDGS = None
33
-
34
- try:
35
- from sympy import sympify
36
- from sympy.core.sympify import SympifyError
37
- except ImportError:
38
- print("Warning: sympy not installed. Math calculator will be limited.")
39
- sympify = None
40
- SympifyError = Exception
41
-
42
- # --- Constants ---
43
- DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
44
-
45
- # --- Advanced Agent Definition ---
46
- class SmartAgent:
47
- def __init__(self):
48
- print("Initializing Local LLM Agent...")
49
-
50
- # Initialize Zephyr-7B model
51
- self.llm = HuggingFaceLLM(
52
- model_name="HuggingFaceH4/zephyr-7b-beta",
53
- tokenizer_name="HuggingFaceH4/zephyr-7b-beta",
54
- context_window=2048,
55
- max_new_tokens=256,
56
- generate_kwargs={"temperature": 0.7, "do_sample": True},
57
- device_map="auto"
58
- )
59
-
60
- # Define tools with real implementations
61
- self.tools = [
62
- FunctionTool.from_defaults(
63
- fn=self.web_search,
64
- name="web_search",
65
- description="Searches the web for current information using DuckDuckGo when questions require up-to-date knowledge"
66
- ),
67
- FunctionTool.from_defaults(
68
- fn=self.math_calculator,
69
- name="math_calculator",
70
- description="Performs mathematical calculations and symbolic math using SymPy when questions involve numbers or equations"
71
- )
72
- ]
73
-
74
- # Create ReAct agent with tools
75
- self.agent = ReActAgent.from_tools(
76
- tools=self.tools,
77
- llm=self.llm,
78
- verbose=True
79
- )
80
- print("Local LLM Agent initialized successfully.")
81
-
82
- def web_search(self, query: str) -> str:
83
- """Real web search using DuckDuckGo"""
84
- print(f"Web search triggered for: {query[:50]}...")
85
-
86
- if not DDGS:
87
- return "Web search unavailable - duckduckgo_search not installed"
88
-
89
- try:
90
- with DDGS() as ddgs:
91
- results = list(ddgs.text(query, max_results=3))
92
- if results:
93
- formatted_results = []
94
- for i, r in enumerate(results, 1):
95
- title = r.get('title', 'No title')
96
- body = r.get('body', 'No description')[:200]
97
- url = r.get('href', '')
98
- formatted_results.append(f"{i}. {title}\n{body}...\nSource: {url}")
99
- return "\n\n".join(formatted_results)
100
- else:
101
- return "No search results found for the query."
102
- except Exception as e:
103
- print(f"Web search error: {e}")
104
- return f"Error during web search: {str(e)}"
105
-
106
- def math_calculator(self, expression: str) -> str:
107
- """Safe math evaluation using SymPy"""
108
- print(f"Math calculation triggered for: {expression}")
109
-
110
- if not sympify:
111
- # Fallback to basic eval with safety checks
112
- try:
113
- # Only allow basic math operations
114
- allowed_chars = set('0123456789+-*/().^ ')
115
- if not all(c in allowed_chars for c in expression.replace(' ', '')):
116
- return "Error: Only basic math operations are allowed"
117
- result = eval(expression.replace('^', '**'))
118
- return str(result)
119
- except Exception as e:
120
- return f"Error: Could not evaluate the mathematical expression - {str(e)}"
121
-
122
- try:
123
- # Use SymPy for safe evaluation
124
- result = sympify(expression).evalf()
125
- return str(result)
126
- except SympifyError as e:
127
- return f"Error: Could not parse the mathematical expression - {str(e)}"
128
- except Exception as e:
129
- return f"Error: Calculation failed - {str(e)}"
130
-
131
- def __call__(self, question: str) -> str:
132
- print(f"Processing question (first 50 chars): {question[:50]}...")
133
- try:
134
- response = self.agent.query(question)
135
- return str(response)
136
- except Exception as e:
137
- print(f"Agent error: {str(e)}")
138
- print(f"Full traceback: {traceback.format_exc()}")
139
- return f"Error processing question: {str(e)}"
140
-
141
-
142
- # --- Submission Logic ---
143
- def run_and_submit_all(profile: gr.OAuthProfile | None):
144
- """
145
- Fetches all questions, runs the agent on them, submits all answers,
146
- and displays the results.
147
- """
148
- space_id = os.getenv("SPACE_ID")
149
-
150
- if profile:
151
- username = f"{profile.username}"
152
- print(f"User logged in: {username}")
153
- else:
154
- print("User not logged in.")
155
- return "Please Login to Hugging Face with the button.", None
156
-
157
- api_url = DEFAULT_API_URL
158
- questions_url = f"{api_url}/questions"
159
- submit_url = f"{api_url}/submit"
160
-
161
- # Instantiate Agent
162
- try:
163
- agent = SmartAgent()
164
- except Exception as e:
165
- print(f"Error instantiating agent: {e}")
166
- print(f"Full traceback: {traceback.format_exc()}")
167
- return f"Error initializing agent: {e}", None
168
-
169
- agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
170
- print(f"Agent code URL: {agent_code}")
171
-
172
- # Fetch Questions
173
- print(f"Fetching questions from: {questions_url}")
174
- try:
175
- response = requests.get(questions_url, timeout=15)
176
- response.raise_for_status()
177
- questions_data = response.json()
178
- if not questions_data:
179
- print("Fetched questions list is empty.")
180
- return "Fetched questions list is empty or invalid format.", None
181
- print(f"Fetched {len(questions_data)} questions.")
182
- except requests.exceptions.RequestException as e:
183
- print(f"Error fetching questions: {e}")
184
- return f"Error fetching questions: {e}", None
185
- except requests.exceptions.JSONDecodeError as e:
186
- print(f"Error decoding JSON response from questions endpoint: {e}")
187
- return f"Error decoding server response for questions: {e}", None
188
- except Exception as e:
189
- print(f"An unexpected error occurred fetching questions: {e}")
190
- return f"An unexpected error occurred fetching questions: {e}", None
191
-
192
- # Run Agent on all questions
193
- results_log = []
194
- answers_payload = []
195
- print(f"Running agent on {len(questions_data)} questions...")
196
-
197
- for i, item in enumerate(questions_data, 1):
198
- task_id = item.get("task_id")
199
- question_text = item.get("question")
200
-
201
- if not task_id or question_text is None:
202
- print(f"Skipping item with missing task_id or question: {item}")
203
- continue
204
-
205
- print(f"Processing question {i}/{len(questions_data)}: {task_id}")
206
-
207
- try:
208
- submitted_answer = agent(question_text)
209
- answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
210
- results_log.append({
211
- "Task ID": task_id,
212
- "Question": question_text[:100] + "..." if len(question_text) > 100 else question_text,
213
- "Submitted Answer": submitted_answer[:200] + "..." if len(submitted_answer) > 200 else submitted_answer
214
- })
215
- print(f"✅ Completed question {i}: {task_id}")
216
- except Exception as e:
217
- print(f"❌ Error running agent on task {task_id}: {e}")
218
- error_answer = f"AGENT ERROR: {str(e)}"
219
- answers_payload.append({"task_id": task_id, "submitted_answer": error_answer})
220
- results_log.append({
221
- "Task ID": task_id,
222
- "Question": question_text[:100] + "..." if len(question_text) > 100 else question_text,
223
- "Submitted Answer": error_answer
224
- })
225
-
226
- if not answers_payload:
227
- print("Agent did not produce any answers to submit.")
228
- return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
229
-
230
- # Prepare submission
231
- submission_data = {
232
- "username": username.strip(),
233
- "agent_code": agent_code,
234
- "answers": answers_payload
235
- }
236
-
237
- status_update = f"Agent finished processing. Submitting {len(answers_payload)} answers for user '{username}'..."
238
- print(status_update)
239
-
240
- # Submit answers
241
- print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
242
- try:
243
- response = requests.post(submit_url, json=submission_data, timeout=60)
244
- response.raise_for_status()
245
- result_data = response.json()
246
-
247
- final_status = (
248
- f"🎉 Submission Successful!\n\n"
249
- f"User: {result_data.get('username')}\n"
250
- f"Overall Score: {result_data.get('score', 'N/A')}% "
251
- f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
252
- f"Message: {result_data.get('message', 'No message received.')}"
253
- )
254
- print("✅ Submission successful!")
255
- results_df = pd.DataFrame(results_log)
256
- return final_status, results_df
257
-
258
- except requests.exceptions.HTTPError as e:
259
- error_detail = f"Server responded with status {e.response.status_code}."
260
- try:
261
- error_json = e.response.json()
262
- error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
263
- except requests.exceptions.JSONDecodeError:
264
- error_detail += f" Response: {e.response.text[:500]}"
265
- status_message = f"❌ Submission Failed: {error_detail}"
266
- print(status_message)
267
- results_df = pd.DataFrame(results_log)
268
- return status_message, results_df
269
-
270
- except requests.exceptions.Timeout:
271
- status_message = "❌ Submission Failed: The request timed out."
272
- print(status_message)
273
- results_df = pd.DataFrame(results_log)
274
- return status_message, results_df
275
-
276
- except requests.exceptions.RequestException as e:
277
- status_message = f"❌ Submission Failed: Network error - {e}"
278
- print(status_message)
279
- results_df = pd.DataFrame(results_log)
280
- return status_message, results_df
281
-
282
- except Exception as e:
283
- status_message = f"❌ An unexpected error occurred during submission: {e}"
284
- print(status_message)
285
- results_df = pd.DataFrame(results_log)
286
- return status_message, results_df
287
-
288
-
289
- # --- Gradio UI ---
290
- with gr.Blocks(title="Local LLM Agent Evaluation") as demo:
291
- gr.Markdown("# 🤖 Local LLM Agent Evaluation Runner")
292
- gr.Markdown(
293
- """
294
- **Instructions:**
295
- 1. 🔐 Log in to your Hugging Face account using the button below
296
- 2. 🚀 Click 'Run Evaluation & Submit All Answers'
297
- 3. ⏳ Wait for the local LLM (Zephyr-7B) to process all questions
298
- 4. 📊 View your results and submission status
299
-
300
- **Features:**
301
- - 🔍 Real web search using DuckDuckGo
302
- - 🧮 Advanced math calculations with SymPy
303
- - 🧠 Powered by HuggingFace Zephyr-7B model
304
- """
305
- )
306
-
307
- with gr.Row():
308
- gr.LoginButton()
309
-
310
- with gr.Row():
311
- run_button = gr.Button(
312
- "🚀 Run Evaluation & Submit All Answers",
313
- variant="primary",
314
- size="lg"
315
- )
316
-
317
- status_output = gr.Textbox(
318
- label="📋 Run Status / Submission Result",
319
- lines=8,
320
- interactive=False,
321
- placeholder="Click the button above to start the evaluation..."
322
- )
323
-
324
- results_table = gr.DataFrame(
325
- label="📊 Questions and Agent Answers",
326
- wrap=True,
327
- interactive=False
328
- )
329
-
330
- # Wire up the button
331
- run_button.click(
332
- fn=run_and_submit_all,
333
- outputs=[status_output, results_table]
334
- )
335
-
336
-
337
- if __name__ == "__main__":
338
- print("\n" + "="*60)
339
- print("🚀 Application Startup at", pd.Timestamp.now().strftime("%Y-%m-%d %H:%M:%S"))
340
- print("="*60)
341
-
342
- space_host_startup = os.getenv("SPACE_HOST")
343
- space_id_startup = os.getenv("SPACE_ID")
344
-
345
- if space_host_startup:
346
- print(f"✅ SPACE_HOST found: {space_host_startup}")
347
- print(f" Runtime URL should be: https://{space_host_startup}")
348
- else:
349
- print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
350
-
351
- if space_id_startup:
352
- print(f"✅ SPACE_ID found: {space_id_startup}")
353
- print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
354
- print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
355
- else:
356
- print("ℹ️ SPACE_ID environment variable not found (running locally?).")
357
-
358
- print("-" * 60)
359
- print("🎯 Launching Gradio Interface for Local LLM Agent Evaluation...")
360
-
361
- # Launch without share=True for Hugging Face Spaces
362
- demo.launch(
363
- server_name="0.0.0.0",
364
- server_port=7860,
365
- show_error=True
366
- )
367
-
368
- readme
369
- ---
370
- title: Template Final Assignment
371
- emoji: 🕵🏻‍♂️
372
- colorFrom: indigo
373
- colorTo: indigo
374
- sdk: gradio
375
- sdk_version: 5.25.2
376
- app_file: app.py
377
- pinned: false
378
- hf_oauth: true
379
- # optional, default duration is 8 hours/480 minutes. Max duration is 30 days/43200 minutes.
380
- hf_oauth_expiration_minutes: 480
381
- ---
382
-
383
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ "90f426e61bed9f1ffce51a95b98945531c35279a"