TaoZewen commited on
Commit
dc7ea3a
·
1 Parent(s): 5c5d260
Files changed (6) hide show
  1. agent.py +214 -0
  2. app.py +35 -66
  3. app2.py +240 -0
  4. requirements copy.txt +21 -0
  5. requirements.txt +16 -19
  6. system_prompt.txt +5 -0
agent.py ADDED
@@ -0,0 +1,214 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """LangGraph Agent"""
2
+ import os
3
+ from dotenv import load_dotenv
4
+ from langgraph.graph import START, StateGraph, MessagesState
5
+ from langgraph.prebuilt import tools_condition
6
+ from langgraph.prebuilt import ToolNode
7
+ from langchain_google_genai import ChatGoogleGenerativeAI
8
+ from langchain_groq import ChatGroq
9
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint, HuggingFaceEmbeddings
10
+ from langchain_community.tools.tavily_search import TavilySearchResults
11
+ from langchain_community.document_loaders import WikipediaLoader
12
+ from langchain_community.document_loaders import ArxivLoader
13
+ from langchain_community.vectorstores import SupabaseVectorStore
14
+ from langchain_core.messages import SystemMessage, HumanMessage
15
+ from langchain_core.tools import tool
16
+ from langchain.tools.retriever import create_retriever_tool
17
+ from supabase.client import Client, create_client
18
+
19
+ load_dotenv()
20
+
21
+ @tool
22
+ def multiply(a: int, b: int) -> int:
23
+ """Multiply two numbers.
24
+
25
+ Args:
26
+ a: first int
27
+ b: second int
28
+ """
29
+ return a * b
30
+
31
+ @tool
32
+ def add(a: int, b: int) -> int:
33
+ """Add two numbers.
34
+
35
+ Args:
36
+ a: first int
37
+ b: second int
38
+ """
39
+ return a + b
40
+
41
+ @tool
42
+ def subtract(a: int, b: int) -> int:
43
+ """Subtract two numbers.
44
+
45
+ Args:
46
+ a: first int
47
+ b: second int
48
+ """
49
+ return a - b
50
+
51
+ @tool
52
+ def divide(a: int, b: int) -> int:
53
+ """Divide two numbers.
54
+
55
+ Args:
56
+ a: first int
57
+ b: second int
58
+ """
59
+ if b == 0:
60
+ raise ValueError("Cannot divide by zero.")
61
+ return a / b
62
+
63
+ @tool
64
+ def modulus(a: int, b: int) -> int:
65
+ """Get the modulus of two numbers.
66
+
67
+ Args:
68
+ a: first int
69
+ b: second int
70
+ """
71
+ return a % b
72
+
73
+ @tool
74
+ def wiki_search(query: str) -> str:
75
+ """Search Wikipedia for a query and return maximum 2 results.
76
+
77
+ Args:
78
+ query: The search query."""
79
+ search_docs = WikipediaLoader(query=query, load_max_docs=2).load()
80
+ formatted_search_docs = "\n\n---\n\n".join(
81
+ [
82
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
83
+ for doc in search_docs
84
+ ])
85
+ return {"wiki_results": formatted_search_docs}
86
+
87
+ @tool
88
+ def web_search(query: str) -> str:
89
+ """Search Tavily for a query and return maximum 3 results.
90
+
91
+ Args:
92
+ query: The search query."""
93
+ search_docs = TavilySearchResults(max_results=3).invoke(query=query)
94
+ formatted_search_docs = "\n\n---\n\n".join(
95
+ [
96
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content}\n</Document>'
97
+ for doc in search_docs
98
+ ])
99
+ return {"web_results": formatted_search_docs}
100
+
101
+ @tool
102
+ def arvix_search(query: str) -> str:
103
+ """Search Arxiv for a query and return maximum 3 result.
104
+
105
+ Args:
106
+ query: The search query."""
107
+ search_docs = ArxivLoader(query=query, load_max_docs=3).load()
108
+ formatted_search_docs = "\n\n---\n\n".join(
109
+ [
110
+ f'<Document source="{doc.metadata["source"]}" page="{doc.metadata.get("page", "")}"/>\n{doc.page_content[:1000]}\n</Document>'
111
+ for doc in search_docs
112
+ ])
113
+ return {"arvix_results": formatted_search_docs}
114
+
115
+
116
+
117
+ # load the system prompt from the file
118
+ with open("system_prompt.txt", "r", encoding="utf-8") as f:
119
+ system_prompt = f.read()
120
+
121
+ # System message
122
+ sys_msg = SystemMessage(content=system_prompt)
123
+
124
+ # build a retriever
125
+ embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2") # dim=768
126
+ supabase: Client = create_client(
127
+ os.environ.get("SUPABASE_URL"),
128
+ os.environ.get("SUPABASE_SERVICE_KEY"))
129
+ vector_store = SupabaseVectorStore(
130
+ client=supabase,
131
+ embedding= embeddings,
132
+ table_name="documents",
133
+ query_name="match_documents_langchain",
134
+ )
135
+ create_retriever_tool = create_retriever_tool(
136
+ retriever=vector_store.as_retriever(),
137
+ name="Question Search",
138
+ description="A tool to retrieve similar questions from a vector store.",
139
+ )
140
+
141
+
142
+
143
+ tools = [
144
+ multiply,
145
+ add,
146
+ subtract,
147
+ divide,
148
+ modulus,
149
+ wiki_search,
150
+ web_search,
151
+ arvix_search,
152
+ ]
153
+
154
+ # Build graph function
155
+ def build_graph(provider: str = "groq"):
156
+ """Build the graph"""
157
+ # Load environment variables from .env file
158
+ if provider == "google":
159
+ # Google Gemini
160
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0)
161
+ elif provider == "groq":
162
+ # Groq https://console.groq.com/docs/models
163
+ llm = ChatGroq(model="qwen-qwq-32b", temperature=0) # optional : qwen-qwq-32b gemma2-9b-it
164
+ elif provider == "huggingface":
165
+ # TODO: Add huggingface endpoint
166
+ llm = ChatHuggingFace(
167
+ llm=HuggingFaceEndpoint(
168
+ url="https://api-inference.huggingface.co/models/Meta-DeepLearning/llama-2-7b-chat-hf",
169
+ temperature=0,
170
+ ),
171
+ )
172
+ else:
173
+ raise ValueError("Invalid provider. Choose 'google', 'groq' or 'huggingface'.")
174
+ # Bind tools to LLM
175
+ llm_with_tools = llm.bind_tools(tools)
176
+
177
+ # Node
178
+ def assistant(state: MessagesState):
179
+ """Assistant node"""
180
+ return {"messages": [llm_with_tools.invoke(state["messages"])]}
181
+
182
+ def retriever(state: MessagesState):
183
+ """Retriever node"""
184
+ similar_question = vector_store.similarity_search(state["messages"][0].content)
185
+ example_msg = HumanMessage(
186
+ content=f"Here I provide a similar question and answer for reference: \n\n{similar_question[0].page_content}",
187
+ )
188
+ return {"messages": [sys_msg] + state["messages"] + [example_msg]}
189
+
190
+ builder = StateGraph(MessagesState)
191
+ builder.add_node("retriever", retriever)
192
+ builder.add_node("assistant", assistant)
193
+ builder.add_node("tools", ToolNode(tools))
194
+ builder.add_edge(START, "retriever")
195
+ builder.add_edge("retriever", "assistant")
196
+ builder.add_conditional_edges(
197
+ "assistant",
198
+ tools_condition,
199
+ )
200
+ builder.add_edge("tools", "assistant")
201
+
202
+ # Compile graph
203
+ return builder.compile()
204
+
205
+ # test
206
+ if __name__ == "__main__":
207
+ question = "When was a picture of St. Thomas Aquinas first added to the Wikipedia page on the Principle of double effect?"
208
+ # Build the graph
209
+ graph = build_graph(provider="groq")
210
+ # Run the graph
211
+ messages = [HumanMessage(content=question)]
212
+ messages = graph.invoke({"messages": messages})
213
+ for m in messages["messages"]:
214
+ m.pretty_print()
app.py CHANGED
@@ -1,58 +1,38 @@
 
1
  import os
 
2
  import gradio as gr
3
  import requests
4
  import pandas as pd
5
- from dotenv import load_dotenv
6
- from gemini_agent import GeminiAgent
 
7
 
8
- import time
9
- import requests
10
 
11
- # Constants
 
12
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
 
 
 
 
 
14
  class BasicAgent:
 
15
  def __init__(self):
16
- print("Initializing the BasicAgent")
17
-
18
- # Get Gemini API key
19
- api_key = os.getenv('GOOGLE_API_KEY')
20
- if not api_key:
21
- raise ValueError("GOOGLE_API_KEY environment variable not set.")
22
-
23
- # Initialize GeminiAgent
24
- self.agent = GeminiAgent(api_key=api_key)
25
- print("GeminiAgent initialized successfully")
26
 
27
  def __call__(self, question: str) -> str:
28
  print(f"Agent received question (first 50 chars): {question[:50]}...")
29
- final_answer = self.agent.run(question)
30
- print(f"Agent returning fixed answer: {final_answer}")
31
- return final_answer
 
 
32
 
33
- def fetch_questions_with_retry(url: str, retries: int = 5, backoff_factor: float = 1.0):
34
- """
35
- 尝试 GET url,遇到 429 时指数退避重试,直到成功或超过重试次数。
36
- """
37
- for i in range(retries):
38
- try:
39
- resp = requests.get(url, timeout=15)
40
- resp.raise_for_status()
41
- return resp.json()
42
- except requests.exceptions.HTTPError as e:
43
- if resp.status_code == 429 and i < retries - 1:
44
- wait = backoff_factor * (2 ** i)
45
- print(f"Received 429, retrying after {wait:.1f}s (attempt {i+1}/{retries})…")
46
- time.sleep(wait)
47
- continue
48
- else:
49
- # 其余 HTTPError 或最后一次 429 都抛出
50
- raise
51
- except Exception:
52
- # 网络等其它错误,直接抛
53
- raise
54
-
55
- def run_and_submit_all(profile: gr.OAuthProfile | None):
56
  """
57
  Fetches all questions, runs the BasicAgent on them, submits all answers,
58
  and displays the results.
@@ -82,36 +62,25 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
82
  print(agent_code)
83
 
84
  # 2. Fetch Questions
85
- # print(f"Fetching questions from: {questions_url}")
86
- # try:
87
- # response = requests.get(questions_url, timeout=15)
88
- # response.raise_for_status()
89
- # questions_data = response.json()
90
- # if not questions_data:
91
- # print("Fetched questions list is empty.")
92
- # return "Fetched questions list is empty or invalid format.", None
93
- # print(f"Fetched {len(questions_data)} questions.")
94
- # except requests.exceptions.RequestException as e:
95
- # print(f"Error fetching questions: {e}")
96
- # return f"Error fetching questions: {e}", None
97
- # except requests.exceptions.JSONDecodeError as e:
98
- # print(f"Error decoding JSON response from questions endpoint: {e}")
99
- # print(f"Response text: {response.text[:500]}")
100
- # return f"Error decoding server response for questions: {e}", None
101
- # except Exception as e:
102
- # print(f"An unexpected error occurred fetching questions: {e}")
103
- # return f"An unexpected error occurred fetching questions: {e}", None
104
-
105
- questions_url = f"{api_url}/questions"
106
  print(f"Fetching questions from: {questions_url}")
107
  try:
108
- questions_data = fetch_questions_with_retry(questions_url, retries=5, backoff_factor=1.0)
 
 
109
  if not questions_data:
110
- return "Fetched questions list is empty or invalid format.", None
 
111
  print(f"Fetched {len(questions_data)} questions.")
112
- except Exception as e:
113
- print(f"Error fetching questions after retries: {e}")
114
  return f"Error fetching questions: {e}", None
 
 
 
 
 
 
 
115
 
116
  # 3. Run your Agent
117
  results_log = []
 
1
+ """ Basic Agent Evaluation Runner"""
2
  import os
3
+ import inspect
4
  import gradio as gr
5
  import requests
6
  import pandas as pd
7
+ from langchain_core.messages import HumanMessage
8
+ from agent import build_graph
9
+
10
 
 
 
11
 
12
+ # (Keep Constants as is)
13
+ # --- Constants ---
14
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
15
 
16
+ # --- Basic Agent Definition ---
17
+ # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
18
+
19
+
20
  class BasicAgent:
21
+ """A langgraph agent."""
22
  def __init__(self):
23
+ print("BasicAgent initialized.")
24
+ self.graph = build_graph()
 
 
 
 
 
 
 
 
25
 
26
  def __call__(self, question: str) -> str:
27
  print(f"Agent received question (first 50 chars): {question[:50]}...")
28
+ # Wrap the question in a HumanMessage from langchain_core
29
+ messages = [HumanMessage(content=question)]
30
+ messages = self.graph.invoke({"messages": messages})
31
+ answer = messages['messages'][-1].content
32
+ return answer[14:]
33
 
34
+
35
+ def run_and_submit_all( profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  """
37
  Fetches all questions, runs the BasicAgent on them, submits all answers,
38
  and displays the results.
 
62
  print(agent_code)
63
 
64
  # 2. Fetch Questions
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  print(f"Fetching questions from: {questions_url}")
66
  try:
67
+ response = requests.get(questions_url, timeout=15)
68
+ response.raise_for_status()
69
+ questions_data = response.json()
70
  if not questions_data:
71
+ print("Fetched questions list is empty.")
72
+ return "Fetched questions list is empty or invalid format.", None
73
  print(f"Fetched {len(questions_data)} questions.")
74
+ except requests.exceptions.RequestException as e:
75
+ print(f"Error fetching questions: {e}")
76
  return f"Error fetching questions: {e}", None
77
+ except requests.exceptions.JSONDecodeError as e:
78
+ print(f"Error decoding JSON response from questions endpoint: {e}")
79
+ print(f"Response text: {response.text[:500]}")
80
+ return f"Error decoding server response for questions: {e}", None
81
+ except Exception as e:
82
+ print(f"An unexpected error occurred fetching questions: {e}")
83
+ return f"An unexpected error occurred fetching questions: {e}", None
84
 
85
  # 3. Run your Agent
86
  results_log = []
app2.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import pandas as pd
5
+ from dotenv import load_dotenv
6
+ from gemini_agent import GeminiAgent
7
+
8
+ import time
9
+ import requests
10
+
11
+ # Constants
12
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
13
+
14
+ class BasicAgent:
15
+ def __init__(self):
16
+ print("Initializing the BasicAgent")
17
+
18
+ # Get Gemini API key
19
+ api_key = os.getenv('GOOGLE_API_KEY')
20
+ if not api_key:
21
+ raise ValueError("GOOGLE_API_KEY environment variable not set.")
22
+
23
+ # Initialize GeminiAgent
24
+ self.agent = GeminiAgent(api_key=api_key)
25
+ print("GeminiAgent initialized successfully")
26
+
27
+ def __call__(self, question: str) -> str:
28
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
29
+ final_answer = self.agent.run(question)
30
+ print(f"Agent returning fixed answer: {final_answer}")
31
+ return final_answer
32
+
33
+ def fetch_questions_with_retry(url: str, retries: int = 5, backoff_factor: float = 1.0):
34
+ """
35
+ 尝试 GET url,遇到 429 时指数退避重试,直到成功或超过重试次数。
36
+ """
37
+ for i in range(retries):
38
+ try:
39
+ resp = requests.get(url, timeout=15)
40
+ resp.raise_for_status()
41
+ return resp.json()
42
+ except requests.exceptions.HTTPError as e:
43
+ if resp.status_code == 429 and i < retries - 1:
44
+ wait = backoff_factor * (2 ** i)
45
+ print(f"Received 429, retrying after {wait:.1f}s (attempt {i+1}/{retries})…")
46
+ time.sleep(wait)
47
+ continue
48
+ else:
49
+ # 其余 HTTPError 或最后一次 429 都抛出
50
+ raise
51
+ except Exception:
52
+ # 网络等其它错误,直接抛
53
+ raise
54
+
55
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
56
+ """
57
+ Fetches all questions, runs the BasicAgent on them, submits all answers,
58
+ and displays the results.
59
+ """
60
+ # --- Determine HF Space Runtime URL and Repo URL ---
61
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
62
+
63
+ if profile:
64
+ username= f"{profile.username}"
65
+ print(f"User logged in: {username}")
66
+ else:
67
+ print("User not logged in.")
68
+ return "Please Login to Hugging Face with the button.", None
69
+
70
+ api_url = DEFAULT_API_URL
71
+ questions_url = f"{api_url}/questions"
72
+ submit_url = f"{api_url}/submit"
73
+
74
+ # 1. Instantiate Agent ( modify this part to create your agent)
75
+ try:
76
+ agent = BasicAgent()
77
+ except Exception as e:
78
+ print(f"Error instantiating agent: {e}")
79
+ return f"Error initializing agent: {e}", None
80
+ # 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)
81
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
82
+ print(agent_code)
83
+
84
+ # 2. Fetch Questions
85
+ # print(f"Fetching questions from: {questions_url}")
86
+ # try:
87
+ # response = requests.get(questions_url, timeout=15)
88
+ # response.raise_for_status()
89
+ # questions_data = response.json()
90
+ # if not questions_data:
91
+ # print("Fetched questions list is empty.")
92
+ # return "Fetched questions list is empty or invalid format.", None
93
+ # print(f"Fetched {len(questions_data)} questions.")
94
+ # except requests.exceptions.RequestException as e:
95
+ # print(f"Error fetching questions: {e}")
96
+ # return f"Error fetching questions: {e}", None
97
+ # except requests.exceptions.JSONDecodeError as e:
98
+ # print(f"Error decoding JSON response from questions endpoint: {e}")
99
+ # print(f"Response text: {response.text[:500]}")
100
+ # return f"Error decoding server response for questions: {e}", None
101
+ # except Exception as e:
102
+ # print(f"An unexpected error occurred fetching questions: {e}")
103
+ # return f"An unexpected error occurred fetching questions: {e}", None
104
+
105
+ questions_url = f"{api_url}/questions"
106
+ print(f"Fetching questions from: {questions_url}")
107
+ try:
108
+ questions_data = fetch_questions_with_retry(questions_url, retries=5, backoff_factor=1.0)
109
+ if not questions_data:
110
+ return "Fetched questions list is empty or invalid format.", None
111
+ print(f"Fetched {len(questions_data)} questions.")
112
+ except Exception as e:
113
+ print(f"Error fetching questions after retries: {e}")
114
+ return f"Error fetching questions: {e}", None
115
+
116
+ # 3. Run your Agent
117
+ results_log = []
118
+ answers_payload = []
119
+ print(f"Running agent on {len(questions_data)} questions...")
120
+ for item in questions_data:
121
+ task_id = item.get("task_id")
122
+ question_text = item.get("question")
123
+ if not task_id or question_text is None:
124
+ print(f"Skipping item with missing task_id or question: {item}")
125
+ continue
126
+ try:
127
+ submitted_answer = agent(question_text)
128
+ answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
129
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
130
+ except Exception as e:
131
+ print(f"Error running agent on task {task_id}: {e}")
132
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
133
+
134
+ if not answers_payload:
135
+ print("Agent did not produce any answers to submit.")
136
+ return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
137
+
138
+ # 4. Prepare Submission
139
+ submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
140
+ status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
141
+ print(status_update)
142
+
143
+ # 5. Submit
144
+ print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
145
+ try:
146
+ response = requests.post(submit_url, json=submission_data, timeout=60)
147
+ response.raise_for_status()
148
+ result_data = response.json()
149
+ final_status = (
150
+ f"Submission Successful!\n"
151
+ f"User: {result_data.get('username')}\n"
152
+ f"Overall Score: {result_data.get('score', 'N/A')}% "
153
+ f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
154
+ f"Message: {result_data.get('message', 'No message received.')}"
155
+ )
156
+ print("Submission successful.")
157
+ results_df = pd.DataFrame(results_log)
158
+ return final_status, results_df
159
+ except requests.exceptions.HTTPError as e:
160
+ error_detail = f"Server responded with status {e.response.status_code}."
161
+ try:
162
+ error_json = e.response.json()
163
+ error_detail += f" Detail: {error_json.get('detail', e.response.text)}"
164
+ except requests.exceptions.JSONDecodeError:
165
+ error_detail += f" Response: {e.response.text[:500]}"
166
+ status_message = f"Submission Failed: {error_detail}"
167
+ print(status_message)
168
+ results_df = pd.DataFrame(results_log)
169
+ return status_message, results_df
170
+ except requests.exceptions.Timeout:
171
+ status_message = "Submission Failed: The request timed out."
172
+ print(status_message)
173
+ results_df = pd.DataFrame(results_log)
174
+ return status_message, results_df
175
+ except requests.exceptions.RequestException as e:
176
+ status_message = f"Submission Failed: Network error - {e}"
177
+ print(status_message)
178
+ results_df = pd.DataFrame(results_log)
179
+ return status_message, results_df
180
+ except Exception as e:
181
+ status_message = f"An unexpected error occurred during submission: {e}"
182
+ print(status_message)
183
+ results_df = pd.DataFrame(results_log)
184
+ return status_message, results_df
185
+
186
+
187
+ # --- Build Gradio Interface using Blocks ---
188
+ with gr.Blocks() as demo:
189
+ gr.Markdown("# Basic Agent Evaluation Runner")
190
+ gr.Markdown(
191
+ """
192
+ **Instructions:**
193
+
194
+ 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
195
+ 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
196
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
197
+
198
+ ---
199
+ **Disclaimers:**
200
+ Once clicking on the "submit button, it can take quite some time ( this is the time for the agent to go through all the questions).
201
+ This space provides a basic setup and is intentionally sub-optimal to encourage you to develop your own, more robust solution. For instance for the delay process of the submit button, a solution could be to cache the answers and submit in a seperate action or even to answer the questions in async.
202
+ """
203
+ )
204
+
205
+ gr.LoginButton()
206
+
207
+ run_button = gr.Button("Run Evaluation & Submit All Answers")
208
+
209
+ status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
210
+ # Removed max_rows=10 from DataFrame constructor
211
+ results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
212
+
213
+ run_button.click(
214
+ fn=run_and_submit_all,
215
+ outputs=[status_output, results_table]
216
+ )
217
+
218
+ if __name__ == "__main__":
219
+ print("\n" + "-"*30 + " App Starting " + "-"*30)
220
+ # Check for SPACE_HOST and SPACE_ID at startup for information
221
+ space_host_startup = os.getenv("SPACE_HOST")
222
+ space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
223
+
224
+ if space_host_startup:
225
+ print(f"✅ SPACE_HOST found: {space_host_startup}")
226
+ print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
227
+ else:
228
+ print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
229
+
230
+ if space_id_startup: # Print repo URLs if SPACE_ID is found
231
+ print(f"✅ SPACE_ID found: {space_id_startup}")
232
+ print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
233
+ print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
234
+ else:
235
+ print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
236
+
237
+ print("-"*(60 + len(" App Starting ")) + "\n")
238
+
239
+ print("Launching Gradio Interface for Basic Agent Evaluation...")
240
+ demo.launch(debug=True, share=False)
requirements copy.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio
2
+ langchain>=0.1.0
3
+ langchain-core>=0.1.0
4
+ langchain-community>=0.0.10
5
+ langchain-google-genai>=0.0.6
6
+ google-generativeai>=0.3.0
7
+ python-dotenv>=1.0.0
8
+ google-api-python-client>=2.108.0
9
+ duckduckgo-search>=4.4
10
+ tiktoken>=0.5.2
11
+ google-cloud-speech>=2.24.0
12
+ requests>=2.31.0
13
+ pydub>=0.25.1
14
+ yt-dlp>=2023.12.30
15
+ smolagents>=0.1.3
16
+ wikipedia>=1.4.0
17
+ Pillow>=10.2.0
18
+ wikipedia-api>=0.6.0
19
+ transformers
20
+ wikipedia
21
+ torch
requirements.txt CHANGED
@@ -1,21 +1,18 @@
1
  gradio
2
- langchain>=0.1.0
3
- langchain-core>=0.1.0
4
- langchain-community>=0.0.10
5
- langchain-google-genai>=0.0.6
6
- google-generativeai>=0.3.0
7
- python-dotenv>=1.0.0
8
- google-api-python-client>=2.108.0
9
- duckduckgo-search>=4.4
10
- tiktoken>=0.5.2
11
- google-cloud-speech>=2.24.0
12
- requests>=2.31.0
13
- pydub>=0.25.1
14
- yt-dlp>=2023.12.30
15
- smolagents>=0.1.3
16
- wikipedia>=1.4.0
17
- Pillow>=10.2.0
18
- wikipedia-api>=0.6.0
19
- transformers
20
  wikipedia
21
- torch
 
 
1
  gradio
2
+ requests
3
+ langchain
4
+ langchain-community
5
+ langchain-core
6
+ langchain-google-genai
7
+ langchain-huggingface
8
+ langchain-groq
9
+ langchain-tavily
10
+ langchain-chroma
11
+ langgraph
12
+ huggingface_hub
13
+ supabase
14
+ arxiv
15
+ pymupdf
 
 
 
 
16
  wikipedia
17
+ pgvector
18
+ python-dotenv
system_prompt.txt ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ You are a helpful assistant tasked with answering questions using a set of tools.
2
+ Now, I will ask you a question. Report your thoughts, and finish your answer with the following template:
3
+ FINAL ANSWER: [YOUR FINAL ANSWER].
4
+ YOUR FINAL ANSWER should be a number OR as few words as possible OR a comma separated list of numbers and/or strings. If you are asked for a number, don't use comma to write your number neither use units such as $ or percent sign unless specified otherwise. If you are asked for a string, don't use articles, neither abbreviations (e.g. for cities), and write the digits in plain text unless specified otherwise. If you are asked for a comma separated list, apply the above rules depending of whether the element to be put in the list is a number or a string.
5
+ Your answer should only start with "FINAL ANSWER: ", then follows with the answer.