ErdemTheFixer commited on
Commit
7e0ae0d
·
verified ·
1 Parent(s): 85fc792

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +95 -81
app.py CHANGED
@@ -1,97 +1,114 @@
1
  import os
2
  import gradio as gr
3
  import requests
4
- import inspect
5
  import pandas as pd
 
6
 
7
- # (Keep Constants as is)
8
  # --- Constants ---
9
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
10
 
11
- # --- Basic Agent Definition ---
12
- #
13
 
14
-
15
- class BasicAgent:
16
  """
17
- Default: Meta-Llama-3-8B-Instruct
 
 
 
18
  """
19
 
20
- # In __init__ of BasicAgent
21
- def __init__(self, model_id: str = "HuggingFaceH4/zephyr-7b-beta"):
22
- model_id_env = os.getenv("HF_MODEL_ID")
23
- self.model_id = model_id_env.strip() if model_id_env else model_id
24
-
25
- self.api_url = f"https://huggingface.co/api/models/{self.model_id}" #https://api-inference.huggingface.co/models/
26
- self.api_token = os.getenv("HF_TOKEN")
27
- if not self.api_token:
28
- raise ValueError("❌ Hugging Face API token not found. Please set 'HF_TOKEN' as env variable.")
29
- self.headers = {"Authorization": f"Bearer {self.api_token}"}
30
- # ... keep session/retries as you have ...
31
-
32
- def __call__(self, question: str,
33
- max_new_tokens: int = 512,
34
- temperature: float = 0.6,
35
- top_p: float = 0.9) -> str:
36
- """
37
- Takes a question, sends it to the LLM via the Inference API, and returns the answer.
38
- """
39
- print(f"📝 Agent received question (preview): {question[:80]}...")
40
 
41
- # Prompt formatting for Llama-3 style
42
- payload = {
43
- "inputs": (
44
- f"<|begin_of_text|><|start_header_id|>user<|end_header_id|>\n\n"
45
- f"{question}\n<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n"
46
- ),
47
- "parameters": {
48
- "max_new_tokens": max_new_tokens,
49
- "return_full_text": False,
50
- "temperature": temperature,
51
- "top_p": top_p,
52
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
 
55
  try:
56
- print("🚀 Querying Hugging Face Inference API...")
57
- response = requests.post(self.api_url, headers=self.headers, json=payload, timeout=16)
58
- response.raise_for_status() # Raise an error for bad status codes
59
-
60
- result = response.json()
61
-
62
- # Handle error response from HF
63
- if isinstance(result, dict) and "error" in result:
64
- print(f"⚠️ HF API Error: {result['error']}")
65
- return f"Error: {result['error']}"
66
-
67
- # Normal expected case: list of dicts
68
- if isinstance(result, list) and result:
69
- answer = result[0].get("generated_text", "")
70
- else:
71
- answer = f"Error: Unexpected API response format: {result}"
72
-
73
- print(f"🤖 Agent returning answer (preview): {answer.strip()[:80]}...")
74
- return answer.strip()
75
-
76
  except requests.exceptions.RequestException as e:
77
- print(f"❌ API request error: {e}")
78
- return f"Error: Could not connect to the Inference API. Details: {e}"
79
  except Exception as e:
80
- print(f"🔥 Unexpected error in agent: {e}")
81
  return f"Error: Unexpected failure while processing. Details: {e}"
82
 
83
 
84
-
85
- def run_and_submit_all( profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  """
87
  Fetches all questions, runs the BasicAgent on them, submits all answers,
88
  and displays the results.
89
  """
90
- # --- Determine HF Space Runtime URL and Repo URL ---
91
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
92
 
93
  if profile:
94
- username= f"{profile.username}"
95
  print(f"User logged in: {username}")
96
  else:
97
  print("User not logged in.")
@@ -101,13 +118,13 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
101
  questions_url = f"{api_url}/questions"
102
  submit_url = f"{api_url}/submit"
103
 
104
- # 1. Instantiate Agent ( modify this part to create your agent)
105
  try:
106
  agent = BasicAgent()
107
  except Exception as e:
108
  print(f"Error instantiating agent: {e}")
109
  return f"Error initializing agent: {e}", None
110
- # 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)
111
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
112
  print(agent_code)
113
 
@@ -118,16 +135,16 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
118
  response.raise_for_status()
119
  questions_data = response.json()
120
  if not questions_data:
121
- print("Fetched questions list is empty.")
122
- return "Fetched questions list is empty or invalid format.", None
123
  print(f"Fetched {len(questions_data)} questions.")
124
  except requests.exceptions.RequestException as e:
125
  print(f"Error fetching questions: {e}")
126
  return f"Error fetching questions: {e}", None
127
  except requests.exceptions.JSONDecodeError as e:
128
- print(f"Error decoding JSON response from questions endpoint: {e}")
129
- print(f"Response text: {response.text[:500]}")
130
- return f"Error decoding server response for questions: {e}", None
131
  except Exception as e:
132
  print(f"An unexpected error occurred fetching questions: {e}")
133
  return f"An unexpected error occurred fetching questions: {e}", None
@@ -147,14 +164,14 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
147
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
148
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
149
  except Exception as e:
150
- print(f"Error running agent on task {task_id}: {e}")
151
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
152
 
153
  if not answers_payload:
154
  print("Agent did not produce any answers to submit.")
155
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
156
 
157
- # 4. Prepare Submission
158
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
159
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
160
  print(status_update)
@@ -226,7 +243,6 @@ with gr.Blocks() as demo:
226
  run_button = gr.Button("Run Evaluation & Submit All Answers")
227
 
228
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
229
- # Removed max_rows=10 from DataFrame constructor
230
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
231
 
232
  run_button.click(
@@ -236,9 +252,8 @@ with gr.Blocks() as demo:
236
 
237
  if __name__ == "__main__":
238
  print("\n" + "-"*30 + " App Starting " + "-"*30)
239
- # Check for SPACE_HOST and SPACE_ID at startup for information
240
  space_host_startup = os.getenv("SPACE_HOST")
241
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
242
 
243
  if space_host_startup:
244
  print(f"✅ SPACE_HOST found: {space_host_startup}")
@@ -246,7 +261,7 @@ if __name__ == "__main__":
246
  else:
247
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
248
 
249
- if space_id_startup: # Print repo URLs if SPACE_ID is found
250
  print(f"✅ SPACE_ID found: {space_id_startup}")
251
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
252
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
@@ -254,6 +269,5 @@ if __name__ == "__main__":
254
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
255
 
256
  print("-"*(60 + len(" App Starting ")) + "\n")
257
-
258
  print("Launching Gradio Interface for Basic Agent Evaluation...")
259
  demo.launch(debug=True, share=False)
 
1
  import os
2
  import gradio as gr
3
  import requests
 
4
  import pandas as pd
5
+ from typing import Optional, Dict, Any
6
 
 
7
  # --- Constants ---
8
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
9
 
 
 
10
 
11
+ class LLMClient:
 
12
  """
13
+ Pluggable LLM client that avoids Hugging Face Inference API.
14
+ Supported providers:
15
+ - openai: uses OpenAI Chat Completions API
16
+ - together: uses Together.ai Chat Completions API (OpenAI-compatible)
17
  """
18
 
19
+ def __init__(self):
20
+ self.provider = (os.getenv("LLM_PROVIDER") or "openai").strip().lower()
21
+
22
+ if self.provider == "openai":
23
+ self.api_key = os.getenv("OPENAI_API_KEY")
24
+ if not self.api_key:
25
+ raise ValueError("OPENAI_API_KEY is required when LLM_PROVIDER=openai.")
26
+ # Default small, fast, and cheap model
27
+ self.model = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
28
+ self.base_url = os.getenv("OPENAI_BASE_URL", "https://api.openai.com/v1")
29
+ self.headers = {
30
+ "Authorization": f"Bearer {self.api_key}",
31
+ "Content-Type": "application/json",
32
+ }
 
 
 
 
 
 
33
 
34
+ elif self.provider == "together":
35
+ self.api_key = os.getenv("TOGETHER_API_KEY")
36
+ if not self.api_key:
37
+ raise ValueError("TOGETHER_API_KEY is required when LLM_PROVIDER=together.")
38
+ # Good instruct model on Together
39
+ self.model = os.getenv("TOGETHER_MODEL", "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo")
40
+ self.base_url = os.getenv("TOGETHER_BASE_URL", "https://api.together.xyz/v1")
41
+ self.headers = {
42
+ "Authorization": f"Bearer {self.api_key}",
43
+ "Content-Type": "application/json",
 
44
  }
45
+
46
+ else:
47
+ raise ValueError("LLM_PROVIDER must be one of: openai, together")
48
+
49
+ def generate(self, prompt: str, max_tokens: int = 512, temperature: float = 0.6, top_p: float = 0.9) -> str:
50
+ """
51
+ Uses Chat Completions-style API to generate text.
52
+ """
53
+ url = f"{self.base_url}/chat/completions"
54
+ payload: Dict[str, Any] = {
55
+ "model": self.model,
56
+ "messages": [
57
+ {"role": "system", "content": "You are a helpful, precise assistant."},
58
+ {"role": "user", "content": prompt},
59
+ ],
60
+ "max_tokens": max_tokens,
61
+ "temperature": temperature,
62
+ "top_p": top_p,
63
  }
64
 
65
  try:
66
+ resp = requests.post(url, headers=self.headers, json=payload, timeout=120)
67
+ if resp.status_code == 404:
68
+ return (
69
+ f"Error: 404 from {self.provider} API. Check model name and base URL.\n"
70
+ f"Requested URL: {url}\nModel: {self.model}"
71
+ )
72
+ resp.raise_for_status()
73
+ data = resp.json()
74
+ text = data.get("choices", [{}])[0].get("message", {}).get("content", "")
75
+ return (text or "").strip()
 
 
 
 
 
 
 
 
 
 
76
  except requests.exceptions.RequestException as e:
77
+ return f"Error: Could not connect to {self.provider} API. Details: {e}"
 
78
  except Exception as e:
 
79
  return f"Error: Unexpected failure while processing. Details: {e}"
80
 
81
 
82
+ class BasicAgent:
83
+ """
84
+ Agent that delegates to a pluggable non-HF provider (OpenAI or Together).
85
+ """
86
+
87
+ def __init__(self):
88
+ self.client = LLMClient()
89
+ print(f"✅ BasicAgent initialized with provider: {self.client.provider}, model: {self.client.model}")
90
+
91
+ def __call__(self, question: str, max_new_tokens: int = 512, temperature: float = 0.6, top_p: float = 0.9) -> str:
92
+ print(f"📝 Agent received question (preview): {question[:80]}...")
93
+ answer = self.client.generate(
94
+ prompt=question,
95
+ max_tokens=max_new_tokens,
96
+ temperature=temperature,
97
+ top_p=top_p,
98
+ )
99
+ print(f"🤖 Agent returning answer (preview): {answer[:80]}...")
100
+ return answer
101
+
102
+
103
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
104
  """
105
  Fetches all questions, runs the BasicAgent on them, submits all answers,
106
  and displays the results.
107
  """
108
+ space_id = os.getenv("SPACE_ID")
 
109
 
110
  if profile:
111
+ username = f"{profile.username}"
112
  print(f"User logged in: {username}")
113
  else:
114
  print("User not logged in.")
 
118
  questions_url = f"{api_url}/questions"
119
  submit_url = f"{api_url}/submit"
120
 
121
+ # 1. Instantiate Agent
122
  try:
123
  agent = BasicAgent()
124
  except Exception as e:
125
  print(f"Error instantiating agent: {e}")
126
  return f"Error initializing agent: {e}", None
127
+
128
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
129
  print(agent_code)
130
 
 
135
  response.raise_for_status()
136
  questions_data = response.json()
137
  if not questions_data:
138
+ print("Fetched questions list is empty.")
139
+ return "Fetched questions list is empty or invalid format.", None
140
  print(f"Fetched {len(questions_data)} questions.")
141
  except requests.exceptions.RequestException as e:
142
  print(f"Error fetching questions: {e}")
143
  return f"Error fetching questions: {e}", None
144
  except requests.exceptions.JSONDecodeError as e:
145
+ print(f"Error decoding JSON response from questions endpoint: {e}")
146
+ print(f"Response text: {response.text[:500]}")
147
+ return f"Error decoding server response for questions: {e}", None
148
  except Exception as e:
149
  print(f"An unexpected error occurred fetching questions: {e}")
150
  return f"An unexpected error occurred fetching questions: {e}", None
 
164
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
165
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
166
  except Exception as e:
167
+ print(f"Error running agent on task {task_id}: {e}")
168
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
169
 
170
  if not answers_payload:
171
  print("Agent did not produce any answers to submit.")
172
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
173
 
174
+ # 4. Prepare Submission
175
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
176
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
177
  print(status_update)
 
243
  run_button = gr.Button("Run Evaluation & Submit All Answers")
244
 
245
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
246
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
247
 
248
  run_button.click(
 
252
 
253
  if __name__ == "__main__":
254
  print("\n" + "-"*30 + " App Starting " + "-"*30)
 
255
  space_host_startup = os.getenv("SPACE_HOST")
256
+ space_id_startup = os.getenv("SPACE_ID")
257
 
258
  if space_host_startup:
259
  print(f"✅ SPACE_HOST found: {space_host_startup}")
 
261
  else:
262
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
263
 
264
+ if space_id_startup:
265
  print(f"✅ SPACE_ID found: {space_id_startup}")
266
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
267
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
 
269
  print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
270
 
271
  print("-"*(60 + len(" App Starting ")) + "\n")
 
272
  print("Launching Gradio Interface for Basic Agent Evaluation...")
273
  demo.launch(debug=True, share=False)