cacaprog commited on
Commit
44507a6
·
verified ·
1 Parent(s): 87b37e7

Update app.py - version 2

Browse files
Files changed (1) hide show
  1. app.py +177 -325
app.py CHANGED
@@ -1,332 +1,188 @@
1
  import os
2
- from dotenv import load_dotenv
3
  import gradio as gr
4
  import requests
 
5
  import pandas as pd
6
- from typing import List
7
- from llama_index.core import VectorStoreIndex, Settings
8
- from llama_index.vector_stores.chroma import ChromaVectorStore
9
  from llama_index.llms.openai import OpenAI
10
- from llama_index.core.tools import FunctionTool
11
- from llama_index.core.agent import ReActAgent
 
 
 
12
  import chromadb
13
  from tavily import TavilyClient
 
 
 
 
14
 
15
  # Load environment variables
 
16
  load_dotenv()
 
 
17
 
18
-
19
- # Agent
20
- class GAIAAgent:
21
  def __init__(self):
22
- print("Initializing GAIA Agent...")
 
 
 
 
23
 
24
- # Initialize components
25
- self.chroma_client = chromadb.PersistentClient(path="./chroma_db")
26
- chroma_collection = self.chroma_client.get_or_create_collection("qa_documents")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
28
- self.index = VectorStoreIndex.from_vector_store(vector_store)
29
-
30
- # Initialize LLM with specific parameters for GAIA
31
- Settings.llm = OpenAI(
32
- model="gpt-4-turbo-preview",
33
- temperature=0.0, # For deterministic answers
34
- max_tokens=500
35
  )
36
- Settings.chunk_size = 512
37
-
38
- # Initialize tools
39
- self.tools = self._initialize_tools()
40
-
41
- # Load system prompt from file
42
- try:
43
- with open('system_prompt.txt', 'r') as f:
44
- self.system_prompt = f.read()
45
- print("✅ System prompt loaded successfully")
46
- except Exception as e:
47
- self.system_prompt = """You are a general AI assistant. I will ask you a question. Report your thoughts, and finish your answer with the following template: FINAL ANSWER: [YOUR FINAL ANSWER]. 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."""
48
- print(f"⚠️ Couldn't load system prompt: {str(e)}. Using fallback prompt.")
49
-
50
- # Create agent
51
- self.agent = ReActAgent.from_tools(
52
- tools=self.tools,
53
- llm=Settings.llm,
54
- system_prompt=self.system_prompt,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  verbose=True,
56
- max_iterations=10
57
  )
58
-
59
- def _initialize_tools(self) -> List[FunctionTool]:
60
- """Initialize all tools for the agent"""
61
- tools = []
62
-
63
- # Math tools
64
- def multiply(a: int, b: int) -> int:
65
- """Multiply two numbers."""
66
- return a * b
67
-
68
- def add(a: int, b: int) -> int:
69
- """Add two numbers."""
70
- return a + b
71
-
72
- def subtract(a: int, b: int) -> int:
73
- """Subtract two numbers."""
74
- return a - b
75
-
76
- def divide(a: int, b: int) -> int:
77
- """Divide two numbers."""
78
- if b == 0:
79
- raise ValueError("Cannot divide by zero")
80
- return a / b
81
-
82
- def modulus(a: int, b: int) -> int:
83
- """Get modulus of two numbers."""
84
- return a % b
85
-
86
- math_tools = [
87
- FunctionTool.from_defaults(fn=multiply, name="multiply"),
88
- FunctionTool.from_defaults(fn=add, name="add"),
89
- FunctionTool.from_defaults(fn=subtract, name="subtract"),
90
- FunctionTool.from_defaults(fn=divide, name="divide"),
91
- FunctionTool.from_defaults(fn=modulus, name="modulus")
92
- ]
93
-
94
- # Search tools
95
- def similar_question_search(question: str) -> str:
96
- """Search for similar questions in vector database."""
97
- query_engine = self.index.as_query_engine(similarity_top_k=3)
98
- response = query_engine.query(question)
99
- return "\n\n".join([
100
- f"Question: {node.text.split('Question: ')[1].split('Final answer:')[0]}\n"
101
- f"Answer: {node.text.split('Final answer: ')[1]}\n"
102
- f"Source: {node.metadata['source']}"
103
- for node in response.source_nodes
104
- ])
105
-
106
- def web_search(query: str) -> str:
107
- """Perform a web search using Tavily API."""
108
- try:
109
- client = TavilyClient(api_key=os.getenv("TAVILY_API_KEY"))
110
- response = client.search(
111
- query=query,
112
- include_answer=True,
113
- search_depth="advanced",
114
- max_results=5
115
- )
116
-
117
- results = []
118
- if response.get("answer"):
119
- results.append(f"Direct Answer: {response['answer']}")
120
-
121
- for result in response.get("results", []):
122
- results.append(
123
- f"Title: {result.get('title', 'N/A')}\n"
124
- f"Link: {result.get('url', 'N/A')}\n"
125
- f"Snippet: {result.get('content', 'N/A')}"
126
- )
127
-
128
- return "\n\n".join(results) if results else "No results found"
129
-
130
- except Exception as e:
131
- return f"Search failed: {str(e)}"
132
-
133
- search_tools = [
134
- FunctionTool.from_defaults(fn=similar_question_search, name="similar_question_search"),
135
- FunctionTool.from_defaults(fn=web_search, name="web_search")
136
- ]
137
 
138
- return math_tools + search_tools
139
-
140
- def __call__(self, question: str) -> dict:
141
- print(f"Processing question: {question[:100]}...")
142
  try:
143
- response = self.agent.chat(question)
144
-
145
- # Extract the FINAL ANSWER from the response
146
- response_str = str(response)
147
- if "FINAL ANSWER:" in response_str:
148
- final_answer = response_str.split("FINAL ANSWER:")[-1].strip()
149
- else:
150
- # If the agent didn't follow instructions, try to extract a clean answer
151
- final_answer = response_str.split("\n")[-1].strip()
152
- final_answer = final_answer.replace('"', '').replace("'", "")
153
-
154
- return {
155
- "model_answer": final_answer,
156
- "reasoning_trace": response_str
157
- }
158
  except Exception as e:
159
- print(f"Error processing question: {e}")
160
- return {
161
- "model_answer": f"Error: {str(e)}",
162
- "reasoning_trace": f"Error occurred: {str(e)}"
163
- }
164
-
165
-
166
- #def run_and_submit_all(profile: gr.OAuthProfile | None):
167
- # """
168
- # Fetches all questions, runs the GAIAAgent on them, submits all answers,
169
- # and displays the results.
170
- # """
171
- # space_id = os.getenv("SPACE_ID")
172
- #
173
- # if profile:
174
- # username = f"{profile.username}"
175
- # print(f"User logged in: {username}")
176
- # else:
177
- # print("User not logged in.")
178
- # return "Please Login to Hugging Face with the button.", None
179
- #
180
- # api_url = "https://agents-course-unit4-scoring.hf.space"
181
- # questions_url = f"{api_url}/questions"
182
- # submit_url = f"{api_url}/submit"
183
- #
184
- # # 1. Instantiate Agent
185
- # try:
186
- # agent = GAIAAgent()
187
- # except Exception as e:
188
- # print(f"Error instantiating agent: {e}")
189
- # return f"Error initializing agent: {e}", None
190
- # # 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)
191
- # agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
192
- # print(agent_code)
193
- #
194
- #
195
- # # 2. Fetch Questions
196
- # print(f"Fetching questions from: {questions_url}")
197
- # try:
198
- # response = requests.get(questions_url, timeout=15)
199
- # response.raise_for_status()
200
- # questions_data = response.json()
201
- # if not questions_data:
202
- # print("Fetched questions list is empty.")
203
- # return "Fetched questions list is empty or invalid format.", None
204
- # print(f"Fetched {len(questions_data)} questions.")
205
- # except requests.exceptions.RequestException as e:
206
- # print(f"Error fetching questions: {e}")
207
- # return f"Error fetching questions: {e}", None
208
- # except requests.exceptions.JSONDecodeError as e:
209
- # print(f"Error decoding JSON response from questions endpoint: {e}")
210
- # print(f"Response text: {response.text[:500]}")
211
- # return f"Error decoding server response for questions: {e}", None
212
- # except Exception as e:
213
- # print(f"An unexpected error occurred fetching questions: {e}")
214
- # return f"An unexpected error occurred fetching questions: {e}", None
215
- #
216
- # # 3. Run your Agent
217
- # results_log = []
218
- # answers_payload = []
219
- # print(f"Running agent on {len(questions_data)} questions...")
220
- # for item in questions_data:
221
- # task_id = item.get("task_id")
222
- # question_text = item.get("question")
223
- # if not task_id or question_text is None:
224
- # print(f"Skipping item with missing task_id or question: {item}")
225
- # continue
226
- # try:
227
- # agent_response = agent(question_text)
228
- # answers_payload.append({
229
- # "task_id": task_id,
230
- # "model_answer": agent_response["model_answer"],
231
- # "reasoning_trace": agent_response["reasoning_trace"]
232
- # })
233
- # results_log.append({
234
- # "Task ID": task_id,
235
- # "Question": question_text,
236
- # "Submitted Answer": agent_response["model_answer"],
237
- # "Reasoning": agent_response["reasoning_trace"]
238
- # })
239
- # except Exception as e:
240
- # print(f"Error running agent on task {task_id}: {e}")
241
- # results_log.append({
242
- # "Task ID": task_id,
243
- # "Question": question_text,
244
- # "Submitted Answer": f"AGENT ERROR: {e}",
245
- # "Reasoning": f"Error occurred: {str(e)}"
246
- # })
247
- #
248
- # if not answers_payload:
249
- # print("Agent did not produce any answers to submit.")
250
- # return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
251
- #
252
- # # 4. Prepare Submission
253
- # submission_data = {
254
- # "username": username.strip(),
255
- # "agent_code": agent_code,
256
- # "answers": answers_payload
257
- # }
258
- # status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
259
- # print(status_update)
260
- #
261
- # # 5. Submit
262
- # print(f"Submitting {len(answers_payload)} answers to: {submit_url}")
263
- # try:
264
- # response = requests.post(submit_url, json=submission_data, timeout=60)
265
- # response.raise_for_status()
266
- # result_data = response.json()
267
- # final_status = (
268
- # f"Submission Successful!\n"
269
- # f"User: {result_data.get('username')}\n"
270
- # f"Overall Score: {result_data.get('score', 'N/A')}% "
271
- # f"({result_data.get('correct_count', '?')}/{result_data.get('total_attempted', '?')} correct)\n"
272
- # f"Message: {result_data.get('message', 'No message received.')}"
273
- # )
274
- # print("Submission successful.")
275
- # results_df = pd.DataFrame(results_log)
276
- # return final_status, results_df
277
- # except Exception as e:
278
- # status_message = f"Submission Failed: {str(e)}"
279
- # print(status_message)
280
- # results_df = pd.DataFrame(results_log)
281
- # return status_message, results_df
282
- #
283
- #
284
- ##--- Build Gradio Interface using Blocks ---
285
- #with gr.Blocks() as demo:
286
- # gr.Markdown("# GAIA Agent Evaluation Runner")
287
- # gr.Markdown(
288
- # """
289
- # **Instructions:**
290
- # 1. Log in to your Hugging Face account using the button below.
291
- # 2. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
292
- # """
293
- # )
294
- #
295
- # gr.LoginButton()
296
- #
297
- # run_button = gr.Button("Run Evaluation & Submit All Answers")
298
- #
299
- # status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
300
- # results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
301
- #
302
- # run_button.click(
303
- # fn=run_and_submit_all,
304
- # outputs=[status_output, results_table]
305
- # )
306
- #
307
- #if __name__ == "__main__":
308
- # print("\n" + "-"*30 + " App Starting " + "-"*30)
309
- # space_host_startup = os.getenv("SPACE_HOST")
310
- # space_id_startup = os.getenv("SPACE_ID")
311
- #
312
- # if space_host_startup:
313
- # print(f"✅ SPACE_HOST found: {space_host_startup}")
314
- # print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
315
- #
316
- # if space_id_startup:
317
- # print(f"✅ SPACE_ID found: {space_id_startup}")
318
- # print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
319
- # print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
320
- #
321
- # print("-"*(60 + len(" App Starting ")) + "\n")
322
- #
323
- # print("Launching Gradio Interface for GAIA Agent Evaluation...")
324
- # demo.launch(debug=True, share=True)
325
-
326
-
327
- def run_and_submit_all( profile: gr.OAuthProfile | None):
328
  """
329
- Fetches all questions, runs the BasicAgent on them, submits all answers,
330
  and displays the results.
331
  """
332
  # --- Determine HF Space Runtime URL and Repo URL ---
@@ -343,13 +199,13 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
343
  questions_url = f"{api_url}/questions"
344
  submit_url = f"{api_url}/submit"
345
 
346
- # 1. Instantiate Agent ( modify this part to create your agent)
347
  try:
348
- agent = BasicAgent()
349
  except Exception as e:
350
  print(f"Error instantiating agent: {e}")
351
  return f"Error initializing agent: {e}", None
352
- # 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)
353
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
354
  print(agent_code)
355
 
@@ -444,20 +300,18 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
444
  results_df = pd.DataFrame(results_log)
445
  return status_message, results_df
446
 
447
-
448
  # --- Build Gradio Interface using Blocks ---
449
  with gr.Blocks() as demo:
450
- gr.Markdown("# Basic Agent Evaluation Runner")
451
  gr.Markdown(
452
  """
453
  **Instructions:**
454
- 1. Please clone this space, then modify the code to define your agent's logic, the tools, the necessary packages, etc ...
455
- 2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
456
- 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
457
- ---
458
- **Disclaimers:**
459
- 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).
460
- 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.
461
  """
462
  )
463
 
@@ -466,7 +320,6 @@ with gr.Blocks() as demo:
466
  run_button = gr.Button("Run Evaluation & Submit All Answers")
467
 
468
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
469
- # Removed max_rows=10 from DataFrame constructor
470
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
471
 
472
  run_button.click(
@@ -476,9 +329,8 @@ with gr.Blocks() as demo:
476
 
477
  if __name__ == "__main__":
478
  print("\n" + "-"*30 + " App Starting " + "-"*30)
479
- # Check for SPACE_HOST and SPACE_ID at startup for information
480
  space_host_startup = os.getenv("SPACE_HOST")
481
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
482
 
483
  if space_host_startup:
484
  print(f"✅ SPACE_HOST found: {space_host_startup}")
@@ -486,7 +338,7 @@ if __name__ == "__main__":
486
  else:
487
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
488
 
489
- if space_id_startup: # Print repo URLs if SPACE_ID is found
490
  print(f"✅ SPACE_ID found: {space_id_startup}")
491
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
492
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
@@ -495,5 +347,5 @@ if __name__ == "__main__":
495
 
496
  print("-"*(60 + len(" App Starting ")) + "\n")
497
 
498
- print("Launching Gradio Interface for Basic Agent Evaluation...")
499
  demo.launch(debug=True, share=False)
 
1
  import os
 
2
  import gradio as gr
3
  import requests
4
+ import inspect
5
  import pandas as pd
6
+ import json
7
+ from llama_index.core.agent.workflow import AgentWorkflow, ReActAgent
 
8
  from llama_index.llms.openai import OpenAI
9
+ from llama_index.core.tools import FunctionTool, QueryEngineTool
10
+ from llama_index.core import VectorStoreIndex
11
+ from llama_index.vector_stores.chroma import ChromaVectorStore
12
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
13
+ from llama_index.core.schema import TextNode
14
  import chromadb
15
  from tavily import TavilyClient
16
+ import asyncio
17
+
18
+ # --- Constants ---
19
+ DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
20
 
21
  # Load environment variables
22
+ from dotenv import load_dotenv
23
  load_dotenv()
24
+ TAVILY_API_KEY = os.getenv("TAVILY_API_KEY")
25
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
26
 
27
+ class ResearchAgent:
 
 
28
  def __init__(self):
29
+ print("Initializing ResearchAgent...")
30
+ self.tavily = TavilyClient(api_key=TAVILY_API_KEY)
31
+ self.llm = OpenAI(model="gpt-4")
32
+ self.workflow = self.initialize_workflow()
33
+ print("ResearchAgent initialized successfully.")
34
 
35
+ def initialize_workflow(self):
36
+ """Initialize all components needed for the workflow"""
37
+ # Build VectorStore
38
+ with open("metadata.jsonl", "r") as f:
39
+ json_QA = [json.loads(line) for line in f]
40
+
41
+ # Initialize ChromaDB
42
+ chroma_client = chromadb.PersistentClient(path="./chroma_db")
43
+ chroma_collection = chroma_client.get_or_create_collection("qa_documents")
44
+
45
+ # Set up embeddings
46
+ embed_model = HuggingFaceEmbedding(model_name="sentence-transformers/all-mpnet-base-v2")
47
+
48
+ # Prepare nodes for indexing
49
+ nodes = []
50
+ for sample in json_QA:
51
+ content = f"Question: {sample['Question']}\n\nFinal answer: {sample['Final answer']}"
52
+ node = TextNode(
53
+ text=content,
54
+ metadata={
55
+ "source": sample['task_id'],
56
+ "level": sample['Level'],
57
+ "final_answer": sample['Final answer'],
58
+ "steps": sample['Annotator Metadata']['Steps'],
59
+ "number_of_steps": sample['Annotator Metadata']['Number of steps'],
60
+ "how_long_did_this_take": sample['Annotator Metadata']['How long did this take?'],
61
+ "tools": sample['Annotator Metadata']['Tools'],
62
+ "number_of_tools": sample['Annotator Metadata']['Number of tools'],
63
+ },
64
+ embedding=embed_model.get_text_embedding(content)
65
+ )
66
+ nodes.append(node)
67
+
68
+ # Create and populate vector store
69
  vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
70
+ index = VectorStoreIndex(
71
+ nodes=nodes,
72
+ embed_model=embed_model,
73
+ vector_store=vector_store,
74
+ store_nodes_override=True
 
 
75
  )
76
+
77
+ # Custom Tavily search function
78
+ def tavily_search(query: str, include_raw_content: bool = False) -> str:
79
+ """Search the web using Tavily. Returns a summary or raw content."""
80
+ response = self.tavily.search(
81
+ query=query,
82
+ include_answer=True,
83
+ include_raw_content=include_raw_content,
84
+ )
85
+ return str(response)
86
+
87
+ # arXiv search tool
88
+ def search_arxiv(query: str, date_range: str = None) -> str:
89
+ """Search arXiv for papers. Date format: '2022-06-01 TO 2022-07-01'."""
90
+ base_url = "http://export.arxiv.org/api/query?"
91
+ params = {"search_query": query, "max_results": 5}
92
+ if date_range:
93
+ params["dateRange"] = date_range
94
+ response = requests.get(base_url, params=params)
95
+ return response.text
96
+
97
+ # Zip code extraction
98
+ def extract_zip_code(location: str) -> str:
99
+ """Get zip code for a location (e.g., 'Fred Howard Park, Florida')."""
100
+ return "34689" # Mocked for demo
101
+
102
+ # Wrap functions as tools
103
+ tavily_tool = FunctionTool.from_defaults(fn=tavily_search)
104
+ arxiv_tool = FunctionTool.from_defaults(fn=search_arxiv)
105
+ zip_tool = FunctionTool.from_defaults(fn=extract_zip_code)
106
+
107
+ # Vector search tool
108
+ query_engine = index.as_query_engine(similarity_top_k=2)
109
+ vector_tool = QueryEngineTool.from_defaults(
110
+ query_engine=query_engine,
111
+ name="vector_qa",
112
+ description="Searches cached Q&A pairs about arXiv papers and species data",
113
+ )
114
+
115
+ # Define agents
116
+ search_agent = ReActAgent(
117
+ name="search_agent",
118
+ description="A research assistant that can search the web and arXiv.",
119
+ tools=[tavily_tool, arxiv_tool, vector_tool],
120
+ llm=self.llm,
121
+ system_prompt="You are a research assistant. First check cached Q&As. Use tools to find answers.",
122
  verbose=True,
 
123
  )
124
+
125
+ data_agent = ReActAgent(
126
+ name="data_agent",
127
+ description="A data extraction agent that can extract and format data.",
128
+ tools=[zip_tool],
129
+ llm=self.llm,
130
+ system_prompt="You extract and format data (e.g., zip codes).",
131
+ verbose=True,
132
+ )
133
+
134
+ math_agent = ReActAgent(
135
+ name="math_agent",
136
+ description="A math agent that can perform calculations.",
137
+ tools=[],
138
+ llm=self.llm,
139
+ system_prompt="You perform calculations and provide answers.",
140
+ verbose=True,
141
+ )
142
+
143
+ sumarizzer_agent = ReActAgent(
144
+ name="sumarizzer_agent",
145
+ description="A summarizer agent that can summarize text.",
146
+ tools=[],
147
+ llm=self.llm,
148
+ system_prompt="""I will summarize the answer. 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.""",
149
+ verbose=True,
150
+ )
151
+
152
+ # Create workflow
153
+ workflow = AgentWorkflow(
154
+ agents=[search_agent, data_agent, math_agent, sumarizzer_agent],
155
+ root_agent="search_agent",
156
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
 
158
+ return workflow
159
+
160
+ async def process_query_async(self, question: str) -> str:
161
+ """Process user query using the workflow (async version)"""
162
  try:
163
+ response = await self.workflow.run(user_msg=question)
164
+ return str(response)
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  except Exception as e:
166
+ return f"An error occurred: {str(e)}"
167
+
168
+ def __call__(self, question: str) -> str:
169
+ """Synchronous wrapper for the async query processing"""
170
+ print(f"Agent received question (first 50 chars): {question[:50]}...")
171
+ try:
172
+ # Run the async function in a new event loop
173
+ loop = asyncio.new_event_loop()
174
+ asyncio.set_event_loop(loop)
175
+ answer = loop.run_until_complete(self.process_query_async(question))
176
+ print(f"Agent returning answer (first 50 chars): {answer[:50]}...")
177
+ return answer
178
+ except Exception as e:
179
+ error_msg = f"Error processing question: {str(e)}"
180
+ print(error_msg)
181
+ return error_msg
182
+
183
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  """
185
+ Fetches all questions, runs the ResearchAgent on them, submits all answers,
186
  and displays the results.
187
  """
188
  # --- Determine HF Space Runtime URL and Repo URL ---
 
199
  questions_url = f"{api_url}/questions"
200
  submit_url = f"{api_url}/submit"
201
 
202
+ # 1. Instantiate Agent
203
  try:
204
+ agent = ResearchAgent()
205
  except Exception as e:
206
  print(f"Error instantiating agent: {e}")
207
  return f"Error initializing agent: {e}", None
208
+
209
  agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
210
  print(agent_code)
211
 
 
300
  results_df = pd.DataFrame(results_log)
301
  return status_message, results_df
302
 
 
303
  # --- Build Gradio Interface using Blocks ---
304
  with gr.Blocks() as demo:
305
+ gr.Markdown("# Research Agent Evaluation Runner")
306
  gr.Markdown(
307
  """
308
  **Instructions:**
309
+
310
+ 1. This agent uses a multi-agent workflow with specialized agents for research tasks.
311
+ 2. Log in to your Hugging Face account using the button below.
312
+ 3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
313
+
314
+ **Note:** Processing all questions may take several minutes due to the complex workflow.
 
315
  """
316
  )
317
 
 
320
  run_button = gr.Button("Run Evaluation & Submit All Answers")
321
 
322
  status_output = gr.Textbox(label="Run Status / Submission Result", lines=5, interactive=False)
 
323
  results_table = gr.DataFrame(label="Questions and Agent Answers", wrap=True)
324
 
325
  run_button.click(
 
329
 
330
  if __name__ == "__main__":
331
  print("\n" + "-"*30 + " App Starting " + "-"*30)
 
332
  space_host_startup = os.getenv("SPACE_HOST")
333
+ space_id_startup = os.getenv("SPACE_ID")
334
 
335
  if space_host_startup:
336
  print(f"✅ SPACE_HOST found: {space_host_startup}")
 
338
  else:
339
  print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
340
 
341
+ if space_id_startup:
342
  print(f"✅ SPACE_ID found: {space_id_startup}")
343
  print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
344
  print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
 
347
 
348
  print("-"*(60 + len(" App Starting ")) + "\n")
349
 
350
+ print("Launching Gradio Interface for Research Agent Evaluation...")
351
  demo.launch(debug=True, share=False)