2stacks Claude commited on
Commit
0c6f69a
·
verified ·
1 Parent(s): b77d916

Fix agent initialization and update project configuration

Browse files

- Replace HfApiModel with InferenceClientModel for proper model initialization
- Remove unsupported 'grammar' parameter from CodeAgent
- Add required final_answer prompt template structure (pre_messages/post_messages)
- Update dependencies: smolagents version, add smolagents[gradio] and ddgs
- Add .gitignore with Python and IDE exclusions
- Update README with setup instructions for local and Docker environments
- Simplify tools: remove get_time_difference, keep get_current_time_in_timezone
- Add DuckDuckGoSearchTool to agent tools list

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (5) hide show
  1. .gitignore +153 -0
  2. README.md +31 -1
  3. app.py +18 -122
  4. prompts.yaml +4 -0
  5. requirements.txt +4 -3
.gitignore ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ PIPFILE.lock
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+ cover/
51
+
52
+ # Translations
53
+ *.mo
54
+ *.pot
55
+
56
+ # Django stuff:
57
+ *.log
58
+ local_settings.py
59
+ db.sqlite3
60
+ db.sqlite3-journal
61
+
62
+ # Flask stuff:
63
+ instance/
64
+ .webassets-cache
65
+
66
+ # Scrapy stuff:
67
+ .scrapy
68
+
69
+ # Sphinx documentation
70
+ docs/_build/
71
+
72
+ # PyBuilder
73
+ .pybuilder/
74
+ target/
75
+
76
+ # Jupyter Notebook
77
+ .ipynb_checkpoints
78
+
79
+ # IPython
80
+ profile_default/
81
+ ipython_config.py
82
+
83
+ # pyenv
84
+ .python-version
85
+
86
+ # pipenv
87
+ Pipfile.lock
88
+
89
+ # poetry
90
+ poetry.lock
91
+
92
+ # pdm
93
+ .pdm.toml
94
+
95
+ # PEP 582
96
+ __pypackages__/
97
+
98
+ # Celery stuff
99
+ celerybeat-schedule
100
+ celerybeat.pid
101
+
102
+ # SageMath parsed files
103
+ *.sage.py
104
+
105
+ # Environments
106
+ .env
107
+ .venv
108
+ env
109
+ venv
110
+ ENV
111
+ env.bak
112
+ venv.bak
113
+
114
+ # Spyder project settings
115
+ .spyderproject
116
+ .spyproject
117
+
118
+ # Rope project settings
119
+ .ropeproject
120
+
121
+ # mkdocs documentation
122
+ /site
123
+
124
+ # mypy
125
+ .mypy_cache/
126
+ .dmypy.json
127
+ dmypy.json
128
+
129
+ # Pyre type checker
130
+ .pyre/
131
+
132
+ # pytype static type analyzer
133
+ .pytype/
134
+
135
+ # Cython debug symbols
136
+ cython_debug/
137
+
138
+ # Gradio
139
+ .gradio/
140
+ flagged/
141
+
142
+ # IDE
143
+ .vscode/
144
+ .idea/
145
+ *.swp
146
+ *.swo
147
+ *~
148
+
149
+ # OS
150
+ .DS_Store
151
+ Thumbs.db
152
+
153
+ # Project specific
README.md CHANGED
@@ -15,4 +15,34 @@ tags:
15
  - agent-course
16
  ---
17
 
18
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  - agent-course
16
  ---
17
 
18
+ Check out the configuration reference at <https://huggingface.co/docs/hub/spaces-config-reference>
19
+
20
+ ## Clone repository
21
+
22
+ ```shell
23
+ git clone https://huggingface.co/spaces/2stacks/First_agent_template
24
+ cd First_agent_template
25
+ ```
26
+
27
+ ## Create and activate Python environment
28
+
29
+ ```shell
30
+ python -m venv env
31
+ source env/bin/activate
32
+ ```
33
+
34
+ ## Install dependencies and run
35
+
36
+ ```shell
37
+ pip install -r requirements.txt
38
+ python app.py
39
+ ```
40
+
41
+ ## Run with Docker
42
+
43
+ ```shell
44
+ docker run -it -p 7860:7860 \
45
+ --platform=linux/amd64 \
46
+ --environment HF_TOKEN="YOUR_VALUE_HERE" \
47
+ registry.hf.space/2stacks-first-agent-template:latest python app.py
48
+ ```
app.py CHANGED
@@ -1,119 +1,12 @@
1
- from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
2
- import requests
3
  import pytz
4
  import yaml
5
- from datetime import datetime, timedelta
6
  from tools.final_answer import FinalAnswerTool
7
 
8
  from Gradio_UI import GradioUI
9
 
10
- # Below is an example of a tool that does nothing. Amaze us with your creativity !
11
- @tool
12
- def get_time_difference(location: str) -> str:
13
- """
14
- Calculates and returns the time difference between a specified location and U.S. Eastern Time.
15
-
16
- This tool fetches the current time for the given location and for the U.S. Eastern Time zone (America/New_York),
17
- then presents a fun, easy-to-read comparison.
18
-
19
- Args:
20
- location: The city or timezone to get the local time for (e.g., "London", "Asia/Tokyo", "Europe/Paris").
21
- """
22
-
23
- def get_time_data(timezone: str):
24
- """Helper function to fetch time data from the World Time API."""
25
- api_url = f"http://worldtimeapi.org/api/timezone/{timezone}"
26
- try:
27
- response = requests.get(api_url)
28
- # Raise an exception for bad status codes (4xx or 5xx)
29
- response.raise_for_status()
30
- return response.json()
31
- except requests.exceptions.RequestException as e:
32
- # This handles network errors, bad status codes, etc.
33
- print(f"API request failed for {timezone}: {e}")
34
- return None
35
-
36
- # Step 1: Get U.S. Eastern Time
37
- et_data = get_time_data("America/New_York")
38
- if not et_data:
39
- return "Oops! I couldn't connect to get the U.S. Eastern Time right now. Please try again later."
40
-
41
- # Step 2: Get time for the user-specified location
42
- # The API can be picky. We'll try the user's input directly first.
43
- # If it fails, we'll try to find a matching timezone.
44
- location_data = get_time_data(location)
45
-
46
- if not location_data:
47
- # Try to find a timezone that contains the location string
48
- try:
49
- all_timezones_response = requests.get("http://worldtimeapi.org/api/timezone")
50
- all_timezones_response.raise_for_status()
51
- all_timezones = all_timezones_response.json()
52
-
53
- # Find the first timezone that ends with the location name
54
- found_timezone = next((tz for tz in all_timezones if tz.lower().endswith(f"/{location.lower()}")), None)
55
-
56
- if found_timezone:
57
- print(f"Found matching timezone: {found_timezone}")
58
- location_data = get_time_data(found_timezone)
59
- else:
60
- return f"Sorry, I couldn't find a timezone for '{location}'. Try a major city or a standard timezone format like 'Europe/London'."
61
- except requests.exceptions.RequestException:
62
- return "Sorry, I'm having trouble searching for that location right now."
63
-
64
-
65
- if not location_data:
66
- return f"I tried my best, but I still couldn't find the time for '{location}'. Are you sure it's spelled correctly?"
67
-
68
- # Step 3: Parse the datetime objects from the API responses
69
- try:
70
- et_time = datetime.fromisoformat(et_data['datetime'])
71
- location_time = datetime.fromisoformat(location_data['datetime'])
72
- location_timezone_name = location.replace('_', ' ').title()
73
- et_timezone_name = "U.S. Eastern Time"
74
- except (ValueError, KeyError):
75
- return "There was an issue processing the time data. It might be a temporary problem."
76
-
77
- # Step 4: Calculate the difference
78
- # We compare based on UTC offset to get the pure time difference
79
- et_offset_str = et_data['utc_offset']
80
- location_offset_str = location_data['utc_offset']
81
-
82
- et_offset = timedelta(hours=int(et_offset_str[1:3]), minutes=int(et_offset_str[4:6]))
83
- if et_offset_str[0] == '-':
84
- et_offset = -et_offset
85
-
86
- location_offset = timedelta(hours=int(location_offset_str[1:3]), minutes=int(location_offset_str[4:6]))
87
- if location_offset_str[0] == '-':
88
- location_offset = -location_offset
89
-
90
- time_difference = location_offset - et_offset
91
-
92
- # Step 5: Format the output string in a fun way
93
- diff_total_seconds = time_difference.total_seconds()
94
- diff_hours = int(diff_total_seconds / 3600)
95
- diff_minutes = int((diff_total_seconds % 3600) / 60)
96
-
97
- comparison = ""
98
- if diff_total_seconds == 0:
99
- comparison = f"{location_timezone_name} is in the same timezone as {et_timezone_name}!"
100
- else:
101
- ahead_or_behind = "ahead of" if diff_total_seconds > 0 else "behind"
102
- # Format the hours and minutes for readability
103
- hour_str = f"{abs(diff_hours)} hour{'s' if abs(diff_hours) != 1 else ''}"
104
- minute_str = f"{abs(diff_minutes)} minute{'s' if abs(diff_minutes) != 1 else ''}"
105
-
106
- if diff_hours != 0 and diff_minutes != 0:
107
- comparison = f"{location_timezone_name} is {hour_str} and {minute_str} {ahead_or_behind} {et_timezone_name}."
108
- elif diff_hours != 0:
109
- comparison = f"{location_timezone_name} is {hour_str} {ahead_or_behind} {et_timezone_name}."
110
- else: # Only minutes are different
111
- comparison = f"{location_timezone_name} is {minute_str} {ahead_or_behind} {et_timezone_name}."
112
-
113
- return (f"Time check! Right now, it's {et_time.strftime('%-I:%M %p')} in {et_timezone_name}, "
114
- f"which means it's {location_time.strftime('%-I:%M %p')} in {location_timezone_name}. "
115
- f"{comparison}")
116
-
117
  @tool
118
  def get_current_time_in_timezone(timezone: str) -> str:
119
  """A tool that fetches the current local time in a specified timezone.
@@ -129,32 +22,35 @@ def get_current_time_in_timezone(timezone: str) -> str:
129
  except Exception as e:
130
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
131
 
 
 
132
 
 
133
  final_answer = FinalAnswerTool()
134
 
135
  # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
136
  # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
137
 
138
- model = HfApiModel(
139
- max_tokens=2096,
140
- temperature=0.5,
141
- model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
142
- custom_role_conversions=None,
 
143
  )
144
 
145
-
146
- # Import tool from Hub
147
- image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
148
-
149
  with open("prompts.yaml", 'r') as stream:
150
  prompt_templates = yaml.safe_load(stream)
151
 
152
  agent = CodeAgent(
153
  model=model,
154
- tools=[final_answer, image_generation_tool, get_time_difference], ## add your tools here (don't remove final answer)
 
 
 
 
155
  max_steps=6,
156
  verbosity_level=1,
157
- grammar=None,
158
  planning_interval=None,
159
  name=None,
160
  description=None,
@@ -162,4 +58,4 @@ agent = CodeAgent(
162
  )
163
 
164
 
165
- GradioUI(agent).launch()
 
1
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, InferenceClientModel, tool
2
+ #import requests
3
  import pytz
4
  import yaml
5
+ from datetime import datetime
6
  from tools.final_answer import FinalAnswerTool
7
 
8
  from Gradio_UI import GradioUI
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  @tool
11
  def get_current_time_in_timezone(timezone: str) -> str:
12
  """A tool that fetches the current local time in a specified timezone.
 
22
  except Exception as e:
23
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
24
 
25
+ # Instantiate the DuckDuckGoSearchTool
26
+ search_tool = DuckDuckGoSearchTool(max_results=5, rate_limit=2.0)
27
 
28
+ # Instantiate the FinalAnswerTool
29
  final_answer = FinalAnswerTool()
30
 
31
  # If the agent does not answer, the model is overloaded, please use another model or the following Hugging Face Endpoint that also contains qwen2.5 coder:
32
  # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
33
 
34
+ model = InferenceClientModel(
35
+ max_tokens=2096,
36
+ temperature=0.5,
37
+ model_id='Qwen/Qwen2.5-Coder-32B-Instruct', # it is possible that this model may be overloaded
38
+ #model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud',
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
+ search_tool,
50
+ get_current_time_in_timezone,
51
+ ], ## add your tools here (don't remove final answer)
52
  max_steps=6,
53
  verbosity_level=1,
 
54
  planning_interval=None,
55
  name=None,
56
  description=None,
 
58
  )
59
 
60
 
61
+ GradioUI(agent).launch()
prompts.yaml CHANGED
@@ -319,3 +319,7 @@
319
  "report": |-
320
  Here is the final answer from your managed agent '{{name}}':
321
  {{final_answer}}
 
 
 
 
 
319
  "report": |-
320
  Here is the final answer from your managed agent '{{name}}':
321
  {{final_answer}}
322
+ "final_answer":
323
+ "pre_messages": ""
324
+ "post_messages": |-
325
+ {{final_answer}}
requirements.txt CHANGED
@@ -1,5 +1,6 @@
1
  markdownify
2
- smolagents==1.13.0
3
- requests
4
  duckduckgo_search
5
- pandas
 
 
1
  markdownify
2
+ smolagents
3
+ #requests
4
  duckduckgo_search
5
+ ddgs
6
+ smolagents[gradio]