razvanfischer commited on
Commit
8609cfe
·
1 Parent(s): ef1b18f

Working demo

Browse files
Files changed (3) hide show
  1. .gitignore +1 -0
  2. app.py +106 -52
  3. requirements.txt +205 -9
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ venv
app.py CHANGED
@@ -1,14 +1,16 @@
1
  import os
2
  import gradio as gr
3
- import requests
4
- import inspect
5
  import pandas as pd
 
6
  import asyncio
 
7
  from llama_index.tools.duckduckgo import DuckDuckGoSearchToolSpec
8
  from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
9
  from llama_index.core.agent.workflow import AgentWorkflow
10
- from llama_index.core import SummaryIndex
11
  from llama_index.readers.web import SimpleWebPageReader
 
 
12
  from llama_index.core.agent.workflow import (
13
  AgentInput,
14
  AgentOutput,
@@ -17,52 +19,103 @@ from llama_index.core.agent.workflow import (
17
  AgentStream,
18
  )
19
 
20
-
21
  # (Keep Constants as is)
22
  # --- Constants ---
23
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
24
 
 
25
  # --- Basic Agent Definition ---
26
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
27
  class BasicAgent:
28
  def __init__(self):
29
  self.llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct")
 
 
 
 
30
  system_prompt = """
31
- You are a helpful assistant that answers questions. If you don't know the answer, you can search the web for information.
32
- If you are searching the web, keep the query very concise in order to get good results.
33
  """
34
- self.agent = AgentWorkflow.from_tools_or_functions([search_web], llm=self.llm,
 
35
  system_prompt=system_prompt)
36
  print("BasicAgent initialized.")
37
-
38
  async def __call__(self, question: str) -> str:
39
  handler = self.agent.run(user_msg=question)
40
  async for event in handler.stream_events():
41
  if isinstance(event, AgentStream):
42
  print(event.delta, end="", flush=True)
43
  elif isinstance(event, ToolCallResult):
44
- print(event.tool_name) # the tool name
45
- print(event.tool_kwargs) # the tool kwargs
46
- print(event.tool_output) # the tool output
47
  response = await handler
48
  return str(response)
49
 
50
- async def search_web(query: str) -> str:
51
- """Useful for using the web to answer questions. Keep the query very concise in order to get good results."""
52
- client = DuckDuckGoSearchToolSpec()
53
- search_res = client.duckduckgo_instant_search(query)
54
- return str(search_res)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
- def run_and_submit_all( profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  """
58
  Fetches all questions, runs the BasicAgent on them, submits all answers,
59
  and displays the results.
60
  """
61
  # --- Determine HF Space Runtime URL and Repo URL ---
62
- space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
63
 
64
  if profile:
65
- username= f"{profile.username}"
66
  print(f"User logged in: {username}")
67
  else:
68
  print("User not logged in.")
@@ -89,16 +142,16 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
89
  response.raise_for_status()
90
  questions_data = response.json()
91
  if not questions_data:
92
- print("Fetched questions list is empty.")
93
- return "Fetched questions list is empty or invalid format.", None
94
  print(f"Fetched {len(questions_data)} questions.")
95
  except requests.exceptions.RequestException as e:
96
  print(f"Error fetching questions: {e}")
97
  return f"Error fetching questions: {e}", None
98
  except requests.exceptions.JSONDecodeError as e:
99
- print(f"Error decoding JSON response from questions endpoint: {e}")
100
- print(f"Response text: {response.text[:500]}")
101
- return f"Error decoding server response for questions: {e}", None
102
  except Exception as e:
103
  print(f"An unexpected error occurred fetching questions: {e}")
104
  return f"An unexpected error occurred fetching questions: {e}", None
@@ -118,14 +171,14 @@ def run_and_submit_all( profile: gr.OAuthProfile | None):
118
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
119
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
120
  except Exception as e:
121
- print(f"Error running agent on task {task_id}: {e}")
122
- results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
123
 
124
  if not answers_payload:
125
  print("Agent did not produce any answers to submit.")
126
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
127
 
128
- # 4. Prepare Submission
129
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
130
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
131
  print(status_update)
@@ -206,28 +259,29 @@ with gr.Blocks() as demo:
206
  )
207
 
208
  if __name__ == "__main__":
209
- # agent = BasicAgent()
210
- # answ = asyncio.run(agent("Who is Michael Jackson?"))
211
-
212
- print("\n" + "-"*30 + " App Starting " + "-"*30)
213
- # Check for SPACE_HOST and SPACE_ID at startup for information
214
- space_host_startup = os.getenv("SPACE_HOST")
215
- space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
216
-
217
- if space_host_startup:
218
- print(f"✅ SPACE_HOST found: {space_host_startup}")
219
- print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
220
- else:
221
- print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
222
-
223
- if space_id_startup: # Print repo URLs if SPACE_ID is found
224
- print(f"✅ SPACE_ID found: {space_id_startup}")
225
- print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
226
- print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
227
- else:
228
- print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
229
-
230
- print("-"*(60 + len(" App Starting ")) + "\n")
231
-
232
- print("Launching Gradio Interface for Basic Agent Evaluation...")
233
- demo.launch(debug=True, share=False)
 
 
1
  import os
2
  import gradio as gr
 
 
3
  import pandas as pd
4
+ from huggingface_hub import InferenceClient
5
  import asyncio
6
+ from llama_index.embeddings.huggingface import HuggingFaceEmbedding
7
  from llama_index.tools.duckduckgo import DuckDuckGoSearchToolSpec
8
  from llama_index.llms.huggingface_api import HuggingFaceInferenceAPI
9
  from llama_index.core.agent.workflow import AgentWorkflow
10
+ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
11
  from llama_index.readers.web import SimpleWebPageReader
12
+ import requests
13
+ from llama_index.readers.wikipedia import WikipediaReader
14
  from llama_index.core.agent.workflow import (
15
  AgentInput,
16
  AgentOutput,
 
19
  AgentStream,
20
  )
21
 
 
22
  # (Keep Constants as is)
23
  # --- Constants ---
24
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
25
 
26
+
27
  # --- Basic Agent Definition ---
28
  # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
29
  class BasicAgent:
30
  def __init__(self):
31
  self.llm = HuggingFaceInferenceAPI(model_name="Qwen/Qwen2.5-Coder-32B-Instruct")
32
+ self.vision_llm = HuggingFaceInferenceAPI(model_name="CohereLabs/aya-vision-32b")
33
+ self.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
34
+ self.search_client = DuckDuckGoSearchToolSpec()
35
+ self.wiki_reader = WikipediaReader()
36
  system_prompt = """
37
+ You are a helpful assistant that answers questions. If you don't know the answer, you can search the web.
 
38
  """
39
+ self.agent = AgentWorkflow.from_tools_or_functions([self.search_web, self.search_wiki, self.webpage_reader],
40
+ llm=self.llm,
41
  system_prompt=system_prompt)
42
  print("BasicAgent initialized.")
43
+
44
  async def __call__(self, question: str) -> str:
45
  handler = self.agent.run(user_msg=question)
46
  async for event in handler.stream_events():
47
  if isinstance(event, AgentStream):
48
  print(event.delta, end="", flush=True)
49
  elif isinstance(event, ToolCallResult):
50
+ print(event.tool_name) # the tool name
51
+ print(event.tool_kwargs) # the tool kwargs
52
+ print(event.tool_output) # the tool output
53
  response = await handler
54
  return str(response)
55
 
56
+ async def describe_images(self, webpage_url: str, query: str) -> str:
57
+ """Extracts and describes images from an input webpage url based on a query."""
58
+
59
+ client = InferenceClient(
60
+ provider="novita",
61
+ api_key="hf_xxxxxxxxxxxxxxxxxxxxxxxx",
62
+ )
63
+
64
+ completion = client.chat.completions.create(
65
+ model="meta-llama/Llama-3.2-11B-Vision-Instruct",
66
+ messages=[
67
+ {
68
+ "role": "user",
69
+ "content": [
70
+ {
71
+ "type": "text",
72
+ "text": "Describe this image in one sentence."
73
+ },
74
+ {
75
+ "type": "image_url",
76
+ "image_url": {
77
+ "url": "https://cdn.britannica.com/61/93061-050-99147DCE/Statue-of-Liberty-Island-New-York-Bay.jpg"
78
+ }
79
+ }
80
+ ]
81
+ }
82
+ ],
83
+ )
84
+
85
+ print(completion.choices[0].message)
86
+
87
+ async def search_wiki(self, query: str) -> str:
88
+ """Useful for browsing Wikipedia to look up specific info."""
89
+ reader = self.wiki_reader
90
+ documents = reader.load_data(pages=[query])
91
+ index = VectorStoreIndex.from_documents(documents, embed_model=self.embed_model)
92
+ search_res = index.as_query_engine(llm=self.llm).query(query)
93
+ return str(search_res)
94
 
95
+ async def search_web(self, query: str) -> str:
96
+ """Useful for using the web to answer questions. Keep the query very concise in order to get good results."""
97
+ client = self.search_client
98
+ search_res = client.duckduckgo_full_search(query)
99
+ return str(search_res)
100
+
101
+ async def webpage_reader(self, webpage_url: str) -> str:
102
+ """Useful for when you want to read and extract information from a specific webpage."""
103
+ documents = SimpleWebPageReader(html_to_text=True).load_data(
104
+ [webpage_url]
105
+ )
106
+ return str(documents)
107
+
108
+
109
+ def run_and_submit_all(profile: gr.OAuthProfile | None):
110
  """
111
  Fetches all questions, runs the BasicAgent on them, submits all answers,
112
  and displays the results.
113
  """
114
  # --- Determine HF Space Runtime URL and Repo URL ---
115
+ space_id = os.getenv("SPACE_ID") # Get the SPACE_ID for sending link to the code
116
 
117
  if profile:
118
+ username = f"{profile.username}"
119
  print(f"User logged in: {username}")
120
  else:
121
  print("User not logged in.")
 
142
  response.raise_for_status()
143
  questions_data = response.json()
144
  if not questions_data:
145
+ print("Fetched questions list is empty.")
146
+ return "Fetched questions list is empty or invalid format.", None
147
  print(f"Fetched {len(questions_data)} questions.")
148
  except requests.exceptions.RequestException as e:
149
  print(f"Error fetching questions: {e}")
150
  return f"Error fetching questions: {e}", None
151
  except requests.exceptions.JSONDecodeError as e:
152
+ print(f"Error decoding JSON response from questions endpoint: {e}")
153
+ print(f"Response text: {response.text[:500]}")
154
+ return f"Error decoding server response for questions: {e}", None
155
  except Exception as e:
156
  print(f"An unexpected error occurred fetching questions: {e}")
157
  return f"An unexpected error occurred fetching questions: {e}", None
 
171
  answers_payload.append({"task_id": task_id, "submitted_answer": submitted_answer})
172
  results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": submitted_answer})
173
  except Exception as e:
174
+ print(f"Error running agent on task {task_id}: {e}")
175
+ results_log.append({"Task ID": task_id, "Question": question_text, "Submitted Answer": f"AGENT ERROR: {e}"})
176
 
177
  if not answers_payload:
178
  print("Agent did not produce any answers to submit.")
179
  return "Agent did not produce any answers to submit.", pd.DataFrame(results_log)
180
 
181
+ # 4. Prepare Submission
182
  submission_data = {"username": username.strip(), "agent_code": agent_code, "answers": answers_payload}
183
  status_update = f"Agent finished. Submitting {len(answers_payload)} answers for user '{username}'..."
184
  print(status_update)
 
259
  )
260
 
261
  if __name__ == "__main__":
262
+ agent = BasicAgent()
263
+ # print(asyncio.run(agent.search_wiki("Michael Jackson (entertainer)")))
264
+ answ = asyncio.run(agent("Search Wikipedia for info on Michael Jackson"))
265
+ # asyncio.run(agent.describe_images("", ""))
266
+ # print("\n" + "-"*30 + " App Starting " + "-"*30)
267
+ # # Check for SPACE_HOST and SPACE_ID at startup for information
268
+ # space_host_startup = os.getenv("SPACE_HOST")
269
+ # space_id_startup = os.getenv("SPACE_ID") # Get SPACE_ID at startup
270
+ #
271
+ # if space_host_startup:
272
+ # print(f" SPACE_HOST found: {space_host_startup}")
273
+ # print(f" Runtime URL should be: https://{space_host_startup}.hf.space")
274
+ # else:
275
+ # print("ℹ️ SPACE_HOST environment variable not found (running locally?).")
276
+ #
277
+ # if space_id_startup: # Print repo URLs if SPACE_ID is found
278
+ # print(f" SPACE_ID found: {space_id_startup}")
279
+ # print(f" Repo URL: https://huggingface.co/spaces/{space_id_startup}")
280
+ # print(f" Repo Tree URL: https://huggingface.co/spaces/{space_id_startup}/tree/main")
281
+ # else:
282
+ # print("ℹ️ SPACE_ID environment variable not found (running locally?). Repo URL cannot be determined.")
283
+ #
284
+ # print("-"*(60 + len(" App Starting ")) + "\n")
285
+ #
286
+ # print("Launching Gradio Interface for Basic Agent Evaluation...")
287
+ # demo.launch(debug=True, share=False)
requirements.txt CHANGED
@@ -1,9 +1,205 @@
1
- gradio
2
- requests
3
- llama-index
4
- llama-index-vector-stores-chroma
5
- llama-index-llms-huggingface-api
6
- llama-index-embeddings-huggingface
7
- llama-index-tools-duckduckgo
8
- llama-index-readers-web
9
- syncio
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ aiofiles==24.1.0
2
+ aiohappyeyeballs==2.6.1
3
+ aiohttp==3.12.2
4
+ aiosignal==1.3.2
5
+ aiosqlite==0.21.0
6
+ annotated-types==0.7.0
7
+ anyio==4.9.0
8
+ asgiref==3.8.1
9
+ attrs==25.3.0
10
+ Authlib==1.6.0
11
+ backoff==2.2.1
12
+ banks==2.1.2
13
+ bcrypt==4.3.0
14
+ beautifulsoup4==4.13.4
15
+ build==1.2.2.post1
16
+ cachetools==5.5.2
17
+ certifi==2025.4.26
18
+ cffi==1.17.1
19
+ charset-normalizer==3.4.2
20
+ chromadb==1.0.10
21
+ chromedriver-autoinstaller==0.6.4
22
+ click==8.2.1
23
+ colorama==0.4.6
24
+ coloredlogs==15.0.1
25
+ cryptography==45.0.3
26
+ cssselect==1.3.0
27
+ dataclasses-json==0.6.7
28
+ defusedxml==0.7.1
29
+ Deprecated==1.2.18
30
+ dirtyjson==1.0.8
31
+ distro==1.9.0
32
+ duckduckgo_search==6.4.2
33
+ durationpy==0.10
34
+ fastapi==0.115.9
35
+ feedfinder2==0.0.4
36
+ feedparser==6.0.11
37
+ ffmpy==0.5.0
38
+ filelock==3.18.0
39
+ filetype==1.2.0
40
+ flatbuffers==25.2.10
41
+ frozenlist==1.6.0
42
+ fsspec==2025.5.1
43
+ google-auth==2.40.2
44
+ googleapis-common-protos==1.70.0
45
+ gradio==5.31.0
46
+ gradio_client==1.10.1
47
+ greenlet==3.2.2
48
+ griffe==1.7.3
49
+ groovy==0.1.2
50
+ grpcio==1.71.0
51
+ h11==0.16.0
52
+ hf-xet==1.1.2
53
+ html2text==2024.2.26
54
+ httpcore==1.0.9
55
+ httptools==0.6.4
56
+ httpx==0.28.1
57
+ huggingface-hub==0.32.2
58
+ humanfriendly==10.0
59
+ idna==3.10
60
+ importlib_metadata==8.6.1
61
+ importlib_resources==6.5.2
62
+ itsdangerous==2.2.0
63
+ jieba3k==0.35.1
64
+ Jinja2==3.1.6
65
+ jiter==0.10.0
66
+ joblib==1.5.1
67
+ jsonschema==4.24.0
68
+ jsonschema-specifications==2025.4.1
69
+ kubernetes==32.0.1
70
+ llama-cloud==0.1.22
71
+ llama-cloud-services==0.6.23
72
+ llama-index==0.12.37
73
+ llama-index-agent-openai==0.4.8
74
+ llama-index-cli==0.4.1
75
+ llama-index-core==0.12.37
76
+ llama-index-embeddings-huggingface==0.5.4
77
+ llama-index-embeddings-openai==0.3.1
78
+ llama-index-indices-managed-llama-cloud==0.6.11
79
+ llama-index-llms-huggingface-api==0.4.3
80
+ llama-index-llms-openai==0.3.44
81
+ llama-index-multi-modal-llms-openai==0.4.3
82
+ llama-index-program-openai==0.3.1
83
+ llama-index-question-gen-openai==0.3.0
84
+ llama-index-readers-file==0.4.8
85
+ llama-index-readers-llama-parse==0.4.0
86
+ llama-index-readers-web==0.4.1
87
+ llama-index-readers-wikipedia==0.3.0
88
+ llama-index-tools-duckduckgo==0.3.0
89
+ llama-index-vector-stores-chroma==0.4.1
90
+ llama-parse==0.6.23
91
+ lxml==5.4.0
92
+ lxml_html_clean==0.4.2
93
+ markdown-it-py==3.0.0
94
+ markdownify==1.1.0
95
+ MarkupSafe==3.0.2
96
+ marshmallow==3.26.1
97
+ mdurl==0.1.2
98
+ mmh3==5.1.0
99
+ mpmath==1.3.0
100
+ multidict==6.4.4
101
+ mypy_extensions==1.1.0
102
+ nest-asyncio==1.6.0
103
+ networkx==3.4.2
104
+ newspaper3k==0.2.8
105
+ nltk==3.9.1
106
+ numpy==1.26.4
107
+ oauthlib==3.2.2
108
+ onnxruntime==1.16.3
109
+ openai==1.82.0
110
+ opentelemetry-api==1.33.1
111
+ opentelemetry-exporter-otlp-proto-common==1.33.1
112
+ opentelemetry-exporter-otlp-proto-grpc==1.33.1
113
+ opentelemetry-instrumentation==0.54b1
114
+ opentelemetry-instrumentation-asgi==0.54b1
115
+ opentelemetry-instrumentation-fastapi==0.54b1
116
+ opentelemetry-proto==1.33.1
117
+ opentelemetry-sdk==1.33.1
118
+ opentelemetry-semantic-conventions==0.54b1
119
+ opentelemetry-util-http==0.54b1
120
+ orjson==3.10.18
121
+ outcome==1.3.0.post0
122
+ overrides==7.7.0
123
+ oxylabs==2.0.0
124
+ packaging==25.0
125
+ pandas==2.2.3
126
+ pillow==11.2.1
127
+ platformdirs==4.3.8
128
+ playwright==1.52.0
129
+ posthog==4.2.0
130
+ primp==0.15.0
131
+ propcache==0.3.1
132
+ protobuf==5.29.4
133
+ pyasn1==0.6.1
134
+ pyasn1_modules==0.4.2
135
+ pycparser==2.22
136
+ pydantic==2.11.5
137
+ pydantic_core==2.33.2
138
+ pydub==0.25.1
139
+ pyee==13.0.0
140
+ Pygments==2.19.1
141
+ pypdf==5.5.0
142
+ PyPika==0.48.9
143
+ pyproject_hooks==1.2.0
144
+ PySocks==1.7.1
145
+ python-dateutil==2.9.0.post0
146
+ python-dotenv==1.1.0
147
+ python-multipart==0.0.20
148
+ pytz==2025.2
149
+ PyYAML==6.0.2
150
+ referencing==0.36.2
151
+ regex==2024.11.6
152
+ requests==2.32.3
153
+ requests-file==2.1.0
154
+ requests-oauthlib==2.0.0
155
+ rich==14.0.0
156
+ rpds-py==0.25.1
157
+ rsa==4.9.1
158
+ ruff==0.11.11
159
+ safehttpx==0.1.6
160
+ safetensors==0.5.3
161
+ scikit-learn==1.6.1
162
+ scipy==1.15.3
163
+ selenium==4.33.0
164
+ semantic-version==2.10.0
165
+ sentence-transformers==4.1.0
166
+ sgmllib3k==1.0.0
167
+ shellingham==1.5.4
168
+ six==1.17.0
169
+ sniffio==1.3.1
170
+ sortedcontainers==2.4.0
171
+ soupsieve==2.7
172
+ spider-client==0.0.27
173
+ SQLAlchemy==2.0.41
174
+ starlette==0.45.3
175
+ striprtf==0.0.26
176
+ sympy==1.14.0
177
+ syncio==0.0.4
178
+ tenacity==9.1.2
179
+ threadpoolctl==3.6.0
180
+ tiktoken==0.9.0
181
+ tinysegmenter==0.3
182
+ tldextract==5.3.0
183
+ tokenizers==0.15.2
184
+ tomlkit==0.13.2
185
+ torch==2.2.2
186
+ tqdm==4.67.1
187
+ transformers==4.36.2
188
+ trio==0.30.0
189
+ trio-websocket==0.12.2
190
+ typer==0.16.0
191
+ typing-inspect==0.9.0
192
+ typing-inspection==0.4.1
193
+ typing_extensions==4.13.2
194
+ tzdata==2025.2
195
+ urllib3==2.4.0
196
+ uvicorn==0.34.2
197
+ uvloop==0.21.0
198
+ watchfiles==1.0.5
199
+ websocket-client==1.8.0
200
+ websockets==15.0.1
201
+ wikipedia==1.4.0
202
+ wrapt==1.17.2
203
+ wsproto==1.2.0
204
+ yarl==1.20.0
205
+ zipp==3.22.0