GustavoDLRA commited on
Commit
edfb300
·
verified ·
1 Parent(s): 81917a3

Added HF environment model

Browse files
Files changed (1) hide show
  1. app.py +191 -5
app.py CHANGED
@@ -4,20 +4,206 @@ 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
- # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  class BasicAgent:
14
  def __init__(self):
15
  print("BasicAgent initialized.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  def __call__(self, question: str) -> str:
17
- print(f"Agent received question (first 50 chars): {question[:50]}...")
18
- fixed_answer = "This is a default answer."
19
- print(f"Agent returning fixed answer: {fixed_answer}")
20
- return fixed_answer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  def run_and_submit_all( profile: gr.OAuthProfile | None):
23
  """
 
4
  import inspect
5
  import pandas as pd
6
 
7
+ # --------- AGENT IMPORTS ---------------
8
+ # Read Data
9
+ # Retriever Tool
10
+ #from langchain_community.retrievers import BM25Retriever
11
+ from langchain_core.tools import Tool
12
+ # Web Search Tool
13
+ from langchain_community.tools import DuckDuckGoSearchRun
14
+ # Agent
15
+ from typing import TypedDict, Annotated
16
+ from langgraph.graph.message import add_messages
17
+ from langchain_core.messages import AnyMessage, HumanMessage, AIMessage, SystemMessage
18
+ from langgraph.prebuilt import ToolNode
19
+ from langgraph.graph import START, StateGraph
20
+ from langgraph.prebuilt import tools_condition
21
+ from langchain_huggingface import ChatHuggingFace, HuggingFaceEndpoint
22
+ # Additional Libraries
23
+ import re
24
+ import requests
25
+ from langchain_community.utilities import WikipediaAPIWrapper
26
+ import subprocess
27
+ # -------------------------------------------------------
28
+
29
  # (Keep Constants as is)
30
  # --- Constants ---
31
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
32
 
33
+ 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."
34
+
35
  # --- Basic Agent Definition ---
36
+
37
+
38
+ llm = HuggingFaceEndpoint(
39
+ repo_id="Qwen/Qwen2.5-7B-Instruct",
40
+ task="text-generation",
41
+ huggingfacehub_api_token=os.getenv("HF_TOKEN"),
42
+ temperature=0,
43
+ max_new_tokens=512,
44
+ )
45
+
46
+ def fetch_webpage(url: str) -> str:
47
+ """Fetch and read the text content of any webpage given its URL."""
48
+ try:
49
+ headers = {"User-Agent": "Mozilla/5.0 (compatible; GAIAAgent/1.0)"}
50
+ resp = requests.get(url.strip(), headers=headers, timeout=15)
51
+ resp.raise_for_status()
52
+
53
+ text = re.sub(r"<[^>]+>", " ", resp.text)
54
+ text = re.sub(r"\s+", " ", text).strip()
55
+
56
+ return text[:4000]
57
+
58
+ except Exception as e:
59
+ return f"Error fetching URL: {e}"
60
+
61
+
62
+ def python_repl(code: str) -> str:
63
+ """Execute Python code for calculations, data parsing, or logic."""
64
+ try:
65
+ result = subprocess.run(
66
+ ["python3", "-c", code],
67
+ capture_output=True,
68
+ text=True,
69
+ timeout=15,
70
+ )
71
+
72
+ output = result.stdout.strip()
73
+ error = result.stderr.strip()
74
+
75
+ if error:
76
+ return f"stderr: {error}\nstdout: {output}"
77
+
78
+ return output if output else "(no output)"
79
+
80
+ except subprocess.TimeoutExpired:
81
+ return "Error: code execution timed out"
82
+
83
+ except Exception as e:
84
+ return f"Error running code: {e}"
85
+
86
+ class AgentState(TypedDict):
87
+ messages: Annotated[list[AnyMessage], add_messages]
88
+
89
  class BasicAgent:
90
  def __init__(self):
91
  print("BasicAgent initialized.")
92
+
93
+ self.search_tool = DuckDuckGoSearchRun()
94
+
95
+ self.wikipedia = WikipediaAPIWrapper(
96
+ top_k_results=2,
97
+ doc_content_chars_max=3000,
98
+ )
99
+
100
+ self.fetch_webpage_tool = Tool(
101
+ name="fetch_webpage",
102
+ func=fetch_webpage,
103
+ description=(
104
+ "Fetch and read the text content of any webpage given its URL. "
105
+ "Use this when a question references a specific URL, or after "
106
+ "web search returns a URL you want to read in full. "
107
+ "Input: a full URL including https://."
108
+ ),
109
+ )
110
+
111
+ self.wikipedia_search_tool = Tool(
112
+ name="wikipedia_search",
113
+ func=self.wikipedia_search,
114
+ description=(
115
+ "Search Wikipedia for factual information about a topic. "
116
+ "Input: a topic or search query."
117
+ ),
118
+ )
119
+
120
+ self.python_repl_tool = Tool(
121
+ name="python_repl",
122
+ func=python_repl,
123
+ description=(
124
+ "Execute Python code for calculations, data parsing, or logic. "
125
+ "Use this for arithmetic, unit conversions, list operations, "
126
+ "or structured data processing. Input: valid Python code."
127
+ ),
128
+ )
129
+
130
+ self.tools = [
131
+ self.search_tool,
132
+ self.fetch_webpage_tool,
133
+ self.wikipedia_search_tool,
134
+ self.python_repl_tool,
135
+ ]
136
+
137
+
138
+
139
+ self.chat = ChatHuggingFace(llm=llm)
140
+
141
+ self.chat_with_tools = self.chat.bind_tools(self.tools)
142
+
143
+ self.graph = self.build_graph()
144
+
145
+ def wikipedia_search(self, query: str) -> str:
146
+ try:
147
+ return self.wikipedia.run(query)
148
+ except Exception as e:
149
+ return f"Wikipedia search error: {e}"
150
+
151
+ def assistant(self, state: AgentState):
152
+ return {
153
+ "messages": [self.chat_with_tools.invoke(state["messages"])]
154
+ }
155
+
156
+ def build_graph(self):
157
+ builder = StateGraph(AgentState)
158
+
159
+ builder.add_node("assistant", self.assistant)
160
+ builder.add_node("tools", ToolNode(self.tools))
161
+
162
+ builder.add_edge(START, "assistant")
163
+
164
+ builder.add_conditional_edges(
165
+ "assistant",
166
+ tools_condition,
167
+ )
168
+
169
+ builder.add_edge("tools", "assistant")
170
+
171
+ return builder.compile()
172
+
173
+ def extract_final_answer(self, text: str) -> str:
174
+ match = re.search(
175
+ r"FINAL ANSWER:\s*(.*)",
176
+ text,
177
+ flags=re.IGNORECASE | re.DOTALL,
178
+ )
179
+
180
+ if match:
181
+ return match.group(1).strip()
182
+
183
+ return text.strip()
184
+
185
  def __call__(self, question: str) -> str:
186
+ print(f"Agent received question: {question[:100]}...")
187
+
188
+ messages = [
189
+ SystemMessage(content=SYSTEM_PROMPT),
190
+ HumanMessage(content=question),
191
+ ]
192
+
193
+ try:
194
+ response = self.graph.invoke({"messages": messages})
195
+ raw_answer = response["messages"][-1].content
196
+
197
+ final_answer = self.extract_final_answer(raw_answer)
198
+
199
+ print(f"Raw answer: {raw_answer}")
200
+ print(f"Submitted answer: {final_answer}")
201
+
202
+ return final_answer
203
+
204
+ except Exception as e:
205
+ print(f"Agent error: {e}")
206
+ return f"AGENT ERROR: {e}"
207
 
208
  def run_and_submit_all( profile: gr.OAuthProfile | None):
209
  """