mujtabarizvi commited on
Commit
d75d9a2
·
verified ·
1 Parent(s): 93dbedf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -17
app.py CHANGED
@@ -6,14 +6,13 @@ import pandas as pd
6
  import re # For parsing LLM output
7
 
8
  # --- HF Inference API for LLM ---
9
- from huggingface_hub import InferenceClient # Corrected import
10
 
11
  # You can choose a different model, but make sure it's good at instruction following and ReAct-style prompting.
12
  LLM_MODEL = "HuggingFaceH4/zephyr-7b-beta" # or "mistralai/Mistral-7B-Instruct-v0.2"
13
 
14
  try:
15
  hf_token = os.getenv("HF_TOKEN")
16
- # Initialize with the corrected InferenceClient
17
  llm_client = InferenceClient(model=LLM_MODEL, token=hf_token)
18
  except Exception as e:
19
  print(f"Error initializing InferenceClient: {e}")
@@ -38,11 +37,9 @@ def search_tool(query: str) -> str:
38
  if results:
39
  return "\n".join([f"Title: {r['title']}\nSnippet: {r['body']}\nURL: {r['href']}" for r in results])
40
  else:
41
- # Provide a more informative message if no results are found
42
  return "No results found for your query. This might mean the query returned no relevant documents, or there could be a temporary issue (e.g., rate limit)."
43
  except Exception as e:
44
  print(f"Error in search_tool: {e}")
45
- # Make the error message slightly more informative about potential causes
46
  return f"Error performing search: {str(e)}. This could be due to a network issue, an invalid query, or a rate limit."
47
 
48
  # 2. Calculator Tool
@@ -57,7 +54,6 @@ def calculator_tool(expression: str) -> str:
57
  """
58
  print(f"Tool: calculator_tool, Expression: {expression}")
59
  try:
60
- # A slightly safer eval using a limited global scope
61
  result = eval(expression, {"__builtins__": {}}, {"sqrt": lambda x: x**0.5, "pi": 3.1415926535})
62
  return str(result)
63
  except Exception as e:
@@ -66,7 +62,7 @@ def calculator_tool(expression: str) -> str:
66
 
67
  # --- Agent Definition ---
68
  class ReActAgent:
69
- def __init__(self, llm_client, tools: dict, max_iterations=7):
70
  print("ReActAgent initialized.")
71
  if llm_client is None:
72
  raise ValueError("LLM client not initialized. Check HF_TOKEN and model availability.")
@@ -81,9 +77,11 @@ class ReActAgent:
81
  ])
82
  self.tool_names = ", ".join(tools.keys())
83
 
 
84
  self.react_prompt_template = inspect.cleandoc(f"""
85
  You are a helpful and observant AI assistant. Your goal is to answer the following question accurately.
86
  You must use a step-by-step thinking process (Thought, Action, Observation).
 
87
 
88
  Available tools:
89
  {self.tool_descriptions}
@@ -95,7 +93,7 @@ class ReActAgent:
95
  Observation: The result of the action.
96
  ... (this Thought/Action/Observation sequence can repeat up to {self.max_iterations} times)
97
  Thought: I now know the final answer.
98
- Final Answer: The final answer to the original input question.
99
 
100
  Begin!
101
  """) + "\nQuestion: {question}\n{scratchpad}"
@@ -105,9 +103,11 @@ class ReActAgent:
105
  try:
106
  response = self.llm.text_generation(
107
  prompt,
108
- max_new_tokens=512,
109
- temperature=0.2,
110
- do_sample=True,
 
 
111
  )
112
  return response.strip()
113
  except Exception as e:
@@ -118,24 +118,32 @@ class ReActAgent:
118
  print(f"ReActAgent received question (first 100 chars): {question[:100]}...")
119
 
120
  scratchpad = ""
 
121
  current_prompt = self.react_prompt_template.format(question=question, scratchpad=scratchpad)
122
 
123
  for i in range(self.max_iterations):
124
  print(f"\nIteration {i+1}")
 
 
 
 
125
  llm_output = self.run_llm(current_prompt)
126
 
127
  if not llm_output:
128
  print("LLM returned empty or error, stopping.")
129
  return "Agent Error: LLM failed to respond."
130
 
 
131
  scratchpad += llm_output + "\n"
132
 
 
133
  final_answer_match = re.search(r"Final Answer:\s*(.*)", llm_output, re.DOTALL | re.IGNORECASE)
134
  if final_answer_match:
135
  answer = final_answer_match.group(1).strip()
136
- print(f"Found Final Answer: {answer}")
137
- return answer
138
 
 
139
  action_match = re.search(r"Action:\s*([a-zA-Z_0-9]+)\[(.*?)\]", llm_output, re.DOTALL)
140
  if action_match:
141
  tool_name = action_match.group(1).strip()
@@ -147,16 +155,20 @@ class ReActAgent:
147
  observation = self.tools[tool_name](tool_input)
148
  except Exception as e:
149
  observation = f"Error executing tool {tool_name}: {e}"
150
- print(f"Observation: {observation[:200]}...")
151
- scratchpad += f"Observation: {observation}\n"
152
  else:
153
  print(f"Unknown tool: {tool_name}")
154
  scratchpad += f"Observation: Error - Unknown tool '{tool_name}'. Available tools: {self.tool_names}\n"
155
  else:
156
- print("No valid action found in LLM output for this iteration.")
 
 
157
 
 
158
  current_prompt = self.react_prompt_template.format(question=question, scratchpad=scratchpad)
159
 
 
160
  # Fallback if max_iterations is reached without a "Final Answer:"
161
  print(f"Max iterations reached for question (first 50 chars): {question[:50]}...")
162
  standard_failure_message = "Agent could not determine an answer within the allowed steps."
@@ -227,7 +239,7 @@ def run_and_submit_all(profile: gr.OAuthProfile | None):
227
  submitted_answer = agent(question_text)
228
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
229
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
230
- print(f"Agent answer for task {task_id}: {submitted_answer[:100]}...")
231
  except Exception as e:
232
  print(f"Error running agent on task {task_id}: {e}")
233
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
@@ -291,7 +303,7 @@ with gr.Blocks() as demo:
291
  1. This Space implements a ReAct (Reasoning-Action) agent using an LLM from the Hugging Face Inference API.
292
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
293
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
294
- 4. The agent uses a search tool (DuckDuckGo) and a calculator tool.
295
  ---
296
  **Disclaimers:**
297
  * LLM responses can be slow, and running through all questions will take time.
 
6
  import re # For parsing LLM output
7
 
8
  # --- HF Inference API for LLM ---
9
+ from huggingface_hub import InferenceClient
10
 
11
  # You can choose a different model, but make sure it's good at instruction following and ReAct-style prompting.
12
  LLM_MODEL = "HuggingFaceH4/zephyr-7b-beta" # or "mistralai/Mistral-7B-Instruct-v0.2"
13
 
14
  try:
15
  hf_token = os.getenv("HF_TOKEN")
 
16
  llm_client = InferenceClient(model=LLM_MODEL, token=hf_token)
17
  except Exception as e:
18
  print(f"Error initializing InferenceClient: {e}")
 
37
  if results:
38
  return "\n".join([f"Title: {r['title']}\nSnippet: {r['body']}\nURL: {r['href']}" for r in results])
39
  else:
 
40
  return "No results found for your query. This might mean the query returned no relevant documents, or there could be a temporary issue (e.g., rate limit)."
41
  except Exception as e:
42
  print(f"Error in search_tool: {e}")
 
43
  return f"Error performing search: {str(e)}. This could be due to a network issue, an invalid query, or a rate limit."
44
 
45
  # 2. Calculator Tool
 
54
  """
55
  print(f"Tool: calculator_tool, Expression: {expression}")
56
  try:
 
57
  result = eval(expression, {"__builtins__": {}}, {"sqrt": lambda x: x**0.5, "pi": 3.1415926535})
58
  return str(result)
59
  except Exception as e:
 
62
 
63
  # --- Agent Definition ---
64
  class ReActAgent:
65
+ def __init__(self, llm_client, tools: dict, max_iterations=7): # max_iterations can be tuned
66
  print("ReActAgent initialized.")
67
  if llm_client is None:
68
  raise ValueError("LLM client not initialized. Check HF_TOKEN and model availability.")
 
77
  ])
78
  self.tool_names = ", ".join(tools.keys())
79
 
80
+ # Refined ReAct prompt template for exact match answers
81
  self.react_prompt_template = inspect.cleandoc(f"""
82
  You are a helpful and observant AI assistant. Your goal is to answer the following question accurately.
83
  You must use a step-by-step thinking process (Thought, Action, Observation).
84
+ The final answer submitted must be an EXACT match to the correct response, without any extra explanations or prefixes being part of the answer itself.
85
 
86
  Available tools:
87
  {self.tool_descriptions}
 
93
  Observation: The result of the action.
94
  ... (this Thought/Action/Observation sequence can repeat up to {self.max_iterations} times)
95
  Thought: I now know the final answer.
96
+ Final Answer: [Provide ONLY the precise answer here. For example, if the question is "What is 2+2?", the Final Answer should be just "4". Do not include any other text or explanations in the answer part itself.]
97
 
98
  Begin!
99
  """) + "\nQuestion: {question}\n{scratchpad}"
 
103
  try:
104
  response = self.llm.text_generation(
105
  prompt,
106
+ max_new_tokens=512, # Adjust if LLM needs more space for thought process
107
+ temperature=0.1, # Lower temperature for more deterministic and precise answers
108
+ do_sample=True, # Often needed if temperature is not 1.0
109
+ # Using temperature < 1.0 makes it do_sample=True by default in many HuggingFace implementations
110
+ # stop_sequences=["Observation:"] # Can help, but might prematurely stop LLM. Parsing is more robust.
111
  )
112
  return response.strip()
113
  except Exception as e:
 
118
  print(f"ReActAgent received question (first 100 chars): {question[:100]}...")
119
 
120
  scratchpad = ""
121
+ # Initial prompt construction for the first turn
122
  current_prompt = self.react_prompt_template.format(question=question, scratchpad=scratchpad)
123
 
124
  for i in range(self.max_iterations):
125
  print(f"\nIteration {i+1}")
126
+ # Note: The scratchpad builds up. Ensure the LLM prompt correctly handles cumulative context.
127
+ # The current template appends the new LLM output and observation to the scratchpad.
128
+ # current_prompt is reconstructed each time using the *updated* scratchpad.
129
+
130
  llm_output = self.run_llm(current_prompt)
131
 
132
  if not llm_output:
133
  print("LLM returned empty or error, stopping.")
134
  return "Agent Error: LLM failed to respond."
135
 
136
+ # Append the LLM's full response (thought and potentially action or final answer) to scratchpad
137
  scratchpad += llm_output + "\n"
138
 
139
+ # Check for "Final Answer:" in the LLM's *current* output
140
  final_answer_match = re.search(r"Final Answer:\s*(.*)", llm_output, re.DOTALL | re.IGNORECASE)
141
  if final_answer_match:
142
  answer = final_answer_match.group(1).strip()
143
+ print(f"Found Final Answer in LLM output: '{answer}'")
144
+ return answer # This is the clean answer
145
 
146
+ # Parse Action from the LLM's *current* output
147
  action_match = re.search(r"Action:\s*([a-zA-Z_0-9]+)\[(.*?)\]", llm_output, re.DOTALL)
148
  if action_match:
149
  tool_name = action_match.group(1).strip()
 
155
  observation = self.tools[tool_name](tool_input)
156
  except Exception as e:
157
  observation = f"Error executing tool {tool_name}: {e}"
158
+ print(f"Observation: {observation[:200]}...") # Print truncated observation
159
+ scratchpad += f"Observation: {observation}\n" # Add observation to scratchpad
160
  else:
161
  print(f"Unknown tool: {tool_name}")
162
  scratchpad += f"Observation: Error - Unknown tool '{tool_name}'. Available tools: {self.tool_names}\n"
163
  else:
164
+ # If no action and no Final Answer, it implies the LLM might be just thinking,
165
+ # or the output is malformed. The loop will continue, using the updated scratchpad.
166
+ print("No valid action found in LLM output for this iteration. LLM might be thinking or output is malformed.")
167
 
168
+ # Reconstruct the prompt for the next iteration with the updated scratchpad
169
  current_prompt = self.react_prompt_template.format(question=question, scratchpad=scratchpad)
170
 
171
+
172
  # Fallback if max_iterations is reached without a "Final Answer:"
173
  print(f"Max iterations reached for question (first 50 chars): {question[:50]}...")
174
  standard_failure_message = "Agent could not determine an answer within the allowed steps."
 
239
  submitted_answer = agent(question_text)
240
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
241
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
242
+ print(f"Agent answer for task {task_id}: '{submitted_answer[:100]}...'") # Added quotes for clarity
243
  except Exception as e:
244
  print(f"Error running agent on task {task_id}: {e}")
245
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
 
303
  1. This Space implements a ReAct (Reasoning-Action) agent using an LLM from the Hugging Face Inference API.
304
  2. Log in to your Hugging Face account using the button below. This uses your HF username for submission.
305
  3. Click 'Run Evaluation & Submit All Answers' to fetch questions, run your agent, submit answers, and see the score.
306
+ 4. The agent uses a search tool (DuckDuckGo) and a calculator tool. The prompt has been refined to encourage EXACT MATCH answers.
307
  ---
308
  **Disclaimers:**
309
  * LLM responses can be slow, and running through all questions will take time.