Spaces:
Sleeping
Sleeping
feat: capability to retrieve news and parse them to extract details
Browse files- .env.example +2 -0
- .gitignore +2 -0
- Dockerfile +5 -1
- Justfile +1 -1
- README.md +7 -1
- requirements.txt +1 -0
- src/Gradio_UI.py +1 -1
- src/app.py +14 -22
- src/tools/__init__.py +0 -0
- src/tools/newsapi_search.py +46 -0
- src/tools/visit_webpage.py +4 -2
- src/tools/web_search.py +2 -1
.env.example
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
HF_TOKEN=
|
2 |
+
NEWSAPI_TOKEN=
|
.gitignore
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
.DS_Store
|
2 |
+
.env
|
Dockerfile
CHANGED
@@ -10,4 +10,8 @@ COPY ./src /app/src
|
|
10 |
|
11 |
COPY ./prompts.yaml /app
|
12 |
|
13 |
-
|
|
|
|
|
|
|
|
|
|
10 |
|
11 |
COPY ./prompts.yaml /app
|
12 |
|
13 |
+
COPY ./.env /app/.env
|
14 |
+
|
15 |
+
EXPOSE 7860
|
16 |
+
|
17 |
+
CMD python -u src/app.py
|
Justfile
CHANGED
@@ -3,4 +3,4 @@ default:
|
|
3 |
|
4 |
run:
|
5 |
docker build --tag 'ai-agents-course' .
|
6 |
-
docker run 'ai-agents-course'
|
|
|
3 |
|
4 |
run:
|
5 |
docker build --tag 'ai-agents-course' .
|
6 |
+
docker run -p 7860:7860 'ai-agents-course'
|
README.md
CHANGED
@@ -15,4 +15,10 @@ tags:
|
|
15 |
- agent-course
|
16 |
---
|
17 |
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
- agent-course
|
16 |
---
|
17 |
|
18 |
+
## Development
|
19 |
+
|
20 |
+
### Setup
|
21 |
+
|
22 |
+
- Copy the `.env.example` into `.env` and pass a Read Only Access HuggingFace Token
|
23 |
+
|
24 |
+
> Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
requirements.txt
CHANGED
@@ -1,6 +1,7 @@
|
|
1 |
duckduckgo_search == 7.4.4
|
2 |
gradio == 5.17.1
|
3 |
markdownify == 0.14.1
|
|
|
4 |
smolagents == 1.9.2
|
5 |
requests == 2.32.3
|
6 |
pandas == 2.2.3
|
|
|
1 |
duckduckgo_search == 7.4.4
|
2 |
gradio == 5.17.1
|
3 |
markdownify == 0.14.1
|
4 |
+
python-dotenv == 1.0.1
|
5 |
smolagents == 1.9.2
|
6 |
requests == 2.32.3
|
7 |
pandas == 2.2.3
|
src/Gradio_UI.py
CHANGED
@@ -17,8 +17,8 @@ import mimetypes
|
|
17 |
import os
|
18 |
import re
|
19 |
import shutil
|
20 |
-
from typing import Optional
|
21 |
|
|
|
22 |
from smolagents.agent_types import AgentAudio, AgentImage, AgentText, handle_agent_output_types
|
23 |
from smolagents.agents import ActionStep, MultiStepAgent
|
24 |
from smolagents.memory import MemoryStep
|
|
|
17 |
import os
|
18 |
import re
|
19 |
import shutil
|
|
|
20 |
|
21 |
+
from typing import Optional
|
22 |
from smolagents.agent_types import AgentAudio, AgentImage, AgentText, handle_agent_output_types
|
23 |
from smolagents.agents import ActionStep, MultiStepAgent
|
24 |
from smolagents.memory import MemoryStep
|
src/app.py
CHANGED
@@ -1,22 +1,17 @@
|
|
1 |
import datetime
|
|
|
2 |
import requests
|
3 |
import pytz
|
4 |
import yaml
|
5 |
|
|
|
6 |
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
|
7 |
from tools.final_answer import FinalAnswerTool
|
|
|
|
|
8 |
from Gradio_UI import GradioUI
|
9 |
|
10 |
-
|
11 |
-
@tool
|
12 |
-
def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type
|
13 |
-
#Keep this format for the description / args / args description but feel free to modify the tool
|
14 |
-
"""A tool that does nothing yet
|
15 |
-
Args:
|
16 |
-
arg1: the first argument
|
17 |
-
arg2: the second argument
|
18 |
-
"""
|
19 |
-
return "What magic will you build ?"
|
20 |
|
21 |
@tool
|
22 |
def get_current_time_in_timezone(timezone: str) -> str:
|
@@ -33,29 +28,27 @@ def get_current_time_in_timezone(timezone: str) -> str:
|
|
33 |
except Exception as e:
|
34 |
return f"Error fetching time for timezone '{timezone}': {str(e)}"
|
35 |
|
36 |
-
|
37 |
final_answer = FinalAnswerTool()
|
38 |
-
|
39 |
-
|
40 |
-
# model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
|
41 |
|
42 |
model = HfApiModel(
|
43 |
max_tokens=2096,
|
44 |
temperature=0.5,
|
45 |
-
model_id='Qwen/Qwen2.5-Coder-32B-Instruct'
|
46 |
custom_role_conversions=None,
|
47 |
)
|
48 |
|
49 |
-
|
50 |
-
# Import tool from Hub
|
51 |
-
image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
|
52 |
-
|
53 |
with open("prompts.yaml", 'r') as stream:
|
54 |
prompt_templates = yaml.safe_load(stream)
|
55 |
|
56 |
agent = CodeAgent(
|
57 |
model=model,
|
58 |
-
tools=[
|
|
|
|
|
|
|
|
|
59 |
max_steps=6,
|
60 |
verbosity_level=1,
|
61 |
grammar=None,
|
@@ -65,5 +58,4 @@ agent = CodeAgent(
|
|
65 |
prompt_templates=prompt_templates
|
66 |
)
|
67 |
|
68 |
-
|
69 |
-
GradioUI(agent).launch()
|
|
|
1 |
import datetime
|
2 |
+
import os
|
3 |
import requests
|
4 |
import pytz
|
5 |
import yaml
|
6 |
|
7 |
+
from dotenv import load_dotenv
|
8 |
from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
|
9 |
from tools.final_answer import FinalAnswerTool
|
10 |
+
from tools.newsapi_search import NewsApiSearch
|
11 |
+
from tools.visit_webpage import VisitWebpageTool
|
12 |
from Gradio_UI import GradioUI
|
13 |
|
14 |
+
load_dotenv()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
15 |
|
16 |
@tool
|
17 |
def get_current_time_in_timezone(timezone: str) -> str:
|
|
|
28 |
except Exception as e:
|
29 |
return f"Error fetching time for timezone '{timezone}': {str(e)}"
|
30 |
|
|
|
31 |
final_answer = FinalAnswerTool()
|
32 |
+
newsapi_search = NewsApiSearch(apikey=os.environ['NEWSAPI_TOKEN'])
|
33 |
+
visit_webpage = VisitWebpageTool()
|
|
|
34 |
|
35 |
model = HfApiModel(
|
36 |
max_tokens=2096,
|
37 |
temperature=0.5,
|
38 |
+
model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
|
39 |
custom_role_conversions=None,
|
40 |
)
|
41 |
|
|
|
|
|
|
|
|
|
42 |
with open("prompts.yaml", 'r') as stream:
|
43 |
prompt_templates = yaml.safe_load(stream)
|
44 |
|
45 |
agent = CodeAgent(
|
46 |
model=model,
|
47 |
+
tools=[
|
48 |
+
final_answer,
|
49 |
+
newsapi_search,
|
50 |
+
visit_webpage,
|
51 |
+
],
|
52 |
max_steps=6,
|
53 |
verbosity_level=1,
|
54 |
grammar=None,
|
|
|
58 |
prompt_templates=prompt_templates
|
59 |
)
|
60 |
|
61 |
+
GradioUI(agent).launch(server_name="0.0.0.0")
|
|
src/tools/__init__.py
ADDED
File without changes
|
src/tools/newsapi_search.py
ADDED
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import requests
|
2 |
+
|
3 |
+
from smolagents.tools import Tool
|
4 |
+
from typing import Any, Optional
|
5 |
+
|
6 |
+
|
7 |
+
class NewsApiSearch(Tool):
|
8 |
+
name = "newsapi_search"
|
9 |
+
description = "Performs a NewsAPI search based on your query then returns the top search News results."
|
10 |
+
inputs = {'query': {'type': 'string', 'description': 'The search query to perform.'}}
|
11 |
+
output_type = "string"
|
12 |
+
|
13 |
+
def __init__(self, max_results=10, apikey='', **kwargs):
|
14 |
+
super().__init__()
|
15 |
+
self.max_results = max_results
|
16 |
+
self.client = NewsApi(apikey)
|
17 |
+
|
18 |
+
def forward(self, query: str) -> str:
|
19 |
+
results = self.client.search(query)
|
20 |
+
return results
|
21 |
+
|
22 |
+
|
23 |
+
class NewsApi:
|
24 |
+
def __init__(self, api_key: str):
|
25 |
+
self.apikey = api_key
|
26 |
+
self.endpoint = "https://newsapi.org/v2/everything"
|
27 |
+
|
28 |
+
def search(self, query: str) -> str:
|
29 |
+
params = {
|
30 |
+
'apiKey': self.apikey,
|
31 |
+
'q': query,
|
32 |
+
}
|
33 |
+
|
34 |
+
response = requests.get(self.endpoint, params=params)
|
35 |
+
|
36 |
+
if response.status_code == 200:
|
37 |
+
data = response.json()
|
38 |
+
articles = data['articles']
|
39 |
+
|
40 |
+
if len(articles) == 0:
|
41 |
+
raise Exception('No news found for the provided query')
|
42 |
+
|
43 |
+
first_result = articles[0]
|
44 |
+
return first_result['url']
|
45 |
+
|
46 |
+
raise Exception('Failed to access NewsAPI Server')
|
src/tools/visit_webpage.py
CHANGED
@@ -1,9 +1,11 @@
|
|
1 |
-
|
2 |
-
from smolagents.tools import Tool
|
3 |
import requests
|
4 |
import markdownify
|
5 |
import smolagents
|
6 |
|
|
|
|
|
|
|
7 |
class VisitWebpageTool(Tool):
|
8 |
name = "visit_webpage"
|
9 |
description = "Visits a webpage at the given url and reads its content as a markdown string. Use this to browse webpages."
|
|
|
1 |
+
import re
|
|
|
2 |
import requests
|
3 |
import markdownify
|
4 |
import smolagents
|
5 |
|
6 |
+
from typing import Any, Optional
|
7 |
+
from smolagents.tools import Tool
|
8 |
+
|
9 |
class VisitWebpageTool(Tool):
|
10 |
name = "visit_webpage"
|
11 |
description = "Visits a webpage at the given url and reads its content as a markdown string. Use this to browse webpages."
|
src/tools/web_search.py
CHANGED
@@ -1,6 +1,7 @@
|
|
|
|
|
|
1 |
from typing import Any, Optional
|
2 |
from smolagents.tools import Tool
|
3 |
-
import duckduckgo_search
|
4 |
|
5 |
class DuckDuckGoSearchTool(Tool):
|
6 |
name = "web_search"
|
|
|
1 |
+
import duckduckgo_search
|
2 |
+
|
3 |
from typing import Any, Optional
|
4 |
from smolagents.tools import Tool
|
|
|
5 |
|
6 |
class DuckDuckGoSearchTool(Tool):
|
7 |
name = "web_search"
|