Lurosm commited on
Commit
1a41076
·
verified ·
1 Parent(s): aee78f2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -58
app.py CHANGED
@@ -1,4 +1,4 @@
1
- from smolagents import CodeAgent,DuckDuckGoSearchTool, HfApiModel,load_tool,tool
2
  import datetime
3
  import requests
4
  import pytz
@@ -10,6 +10,7 @@ from typing import Optional, Dict, Any, List
10
  import requests
11
  from pydantic import BaseModel, Field, field_validator
12
  from typing import Optional, Union
 
13
 
14
  class PDOKLocationSearchInput(BaseModel):
15
  postal_code: Optional[str] = Field(None, description="Postal code in the format '1234 AA'.")
@@ -22,7 +23,7 @@ class PDOKLocationSearchInput(BaseModel):
22
  if v is not None and (len(v) != 7 or not v[0:4].isdigit() or v[4] != " " or not v[5:7].isalpha()):
23
  raise ValueError("Invalid postal code format. It must be '1234 AA'.")
24
  return v
25
-
26
  def construct_query(self) -> str:
27
  """Constructs the query string based on provided inputs."""
28
  if self.postal_code and self.house_number:
@@ -32,27 +33,164 @@ class PDOKLocationSearchInput(BaseModel):
32
  else:
33
  return ""
34
 
35
- class PDOKLocationInfo(BaseModel): # This is not used in the tool's return anymore
36
- type: str
37
- weergavenaam: str
38
- straatnaam: Optional[str] = None
39
- huisnummer: Optional[int] = None
40
- huisletter: Optional[str] = None
41
- huisnummertoevoeging: Optional[str] = None
42
- postcode: Optional[str] = None
43
- woonplaatsnaam: Optional[str] = None
44
- gemeentenaam: Optional[str] = None
45
- provincienaam: Optional[str] = None
46
- centroide_ll: Optional[str] = None
47
- centroide_rd: Optional[str] = None
48
-
49
- class Config:
50
- extra = "allow" # This will allow extra fields from the API response
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
 
 
52
  @tool
53
  def pdok_location_info(postal_code: Optional[str] = None, house_number: Optional[str] = None, street_name: Optional[str] = None, city: Optional[str] = None) -> str:
54
- """Provides information about a Dutch address or postal code, including a Google Maps link.
55
-
56
  Args:
57
  postal_code: Postal code in the format '1234 AA'.
58
  house_number: House number of the address.
@@ -60,19 +198,19 @@ def pdok_location_info(postal_code: Optional[str] = None, house_number: Optional
60
  city: Name of the city.
61
 
62
  Returns:
63
- str: JSON string containing the location information, including a Google Maps link, or an error message.
64
  """
65
-
66
  debug_info = []
67
  debug_info.append(f"Input values:\n"
68
  f" Postal code: {postal_code}\n"
69
  f" House number: {house_number}\n"
70
  f" Street name: {street_name}\n"
71
  f" City: {city}")
72
-
73
  base_url = "https://api.pdok.nl/bzk/locatieserver/search/v3_1/free"
74
  headers = {"accept": "application/json"}
75
-
76
  input_data = PDOKLocationSearchInput(postal_code=postal_code, house_number=house_number, street_name=street_name, city=city)
77
  query_string = input_data.construct_query()
78
 
@@ -84,35 +222,36 @@ def pdok_location_info(postal_code: Optional[str] = None, house_number: Optional
84
  params = {
85
  "q": query_string,
86
  "fl": "*",
87
- "fq": "type:(gemeente OR woonplaats OR postcode OR adres)",
88
  "df": "tekst",
 
89
  "bq": "type:gemeente^1.5",
90
  "bq": "type:woonplaats^1.5",
 
91
  "bq": "type:postcode^0.5",
92
  "bq": "type:adres^1",
93
  "start": 0,
94
- "rows": 1,
95
  "sort": "score desc,sortering asc,weergavenaam asc",
96
  "wt": "json",
97
  }
98
-
99
  try:
100
- response = requests.get(base_url, params=params, headers=headers)
101
  debug_info.append(f"Response status code: {response.status_code}")
102
-
103
  response.raise_for_status()
104
  data = response.json()
105
-
106
  docs = data.get("response", {}).get("docs", [])
107
  debug_info.append(f"Number of docs found: {len(docs)}")
108
-
109
  if not docs:
110
  return f"Error: No results found\nDebug info:\n" + "\n".join(debug_info)
111
 
112
  first_result = docs[0]
113
  debug_info.append(f"First result data: {first_result}")
114
-
115
- # Create a dictionary with only the fields we need, *including* the Google Maps link
116
  location_info = {
117
  "straatnaam": first_result.get("straatnaam", ""),
118
  "huisnummer": first_result.get("huisnummer", ""),
@@ -126,24 +265,38 @@ def pdok_location_info(postal_code: Optional[str] = None, house_number: Optional
126
  "centroide_rd": first_result.get("centroide_rd", "")
127
  }
128
 
129
- # Add Google Maps link *to the dictionary that will be returned*
130
  centroide_ll = location_info.get('centroide_ll')
131
  if centroide_ll:
132
  lon, lat = centroide_ll.replace("POINT(", "").replace(")", "").split()
133
  location_info["google_maps_url"] = f"https://www.google.com/maps/search/?api=1&query={lat},{lon}"
134
-
135
- return json.dumps(location_info) # Return the dictionary as a JSON string
136
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
  except requests.exceptions.RequestException as e:
138
  return f"Error during API request: {e}\nDebug info:\n" + "\n".join(debug_info)
139
  except (ValueError, KeyError) as e:
140
  return f"Error processing API response: {e}\nDebug info:\n" + "\n".join(debug_info)
141
-
142
- # --- Rest of your code (agent definition, etc.) remains the same ---
143
 
144
  @tool
145
- def my_custom_tool(arg1:str, arg2:int)-> str: #it's import to specify the return type
146
- #Keep this format for the description / args / args description but feel free to modify the tool
147
  """A tool that does nothing yet
148
  Args:
149
  arg1: the first argument
@@ -158,39 +311,31 @@ def get_current_time_in_timezone(timezone: str) -> str:
158
  timezone: A string representing a valid timezone (e.g., 'America/New_York').
159
  """
160
  try:
161
- # Create timezone object
162
  tz = pytz.timezone(timezone)
163
- # Get current time in that timezone
164
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
165
  return f"The current local time in {timezone} is: {local_time}"
166
  except Exception as e:
167
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
168
 
169
-
170
  final_answer = FinalAnswerTool()
171
 
172
- # 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:
173
- # model_id='https://pflgm2locj2t89co.us-east-1.aws.endpoints.huggingface.cloud'
174
-
175
  model = HfApiModel(
176
- max_tokens=2096,
177
- temperature=0.5,
178
- model_id='Qwen/Qwen2.5-Coder-32B-Instruct',# it is possible that this model may be overloaded
179
- custom_role_conversions=None,
180
  )
181
 
182
-
183
- # Import tool from Hub
184
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
185
 
186
  with open("prompts.yaml", 'r') as stream:
187
  prompt_templates = yaml.safe_load(stream)
188
-
189
  agent = CodeAgent(
190
  model=model,
191
- tools=[final_answer, get_current_time_in_timezone, pdok_location_info], ## add your tools here (don't remove final answer)
192
- max_steps=3,
193
- verbosity_level=1,
194
  grammar=None,
195
  planning_interval=None,
196
  name=None,
@@ -198,5 +343,4 @@ agent = CodeAgent(
198
  prompt_templates=prompt_templates
199
  )
200
 
201
-
202
  GradioUI(agent).launch()
 
1
+ from smolagents import CodeAgent, DuckDuckGoSearchTool, HfApiModel, load_tool, tool
2
  import datetime
3
  import requests
4
  import pytz
 
10
  import requests
11
  from pydantic import BaseModel, Field, field_validator
12
  from typing import Optional, Union
13
+ import functools
14
 
15
  class PDOKLocationSearchInput(BaseModel):
16
  postal_code: Optional[str] = Field(None, description="Postal code in the format '1234 AA'.")
 
23
  if v is not None and (len(v) != 7 or not v[0:4].isdigit() or v[4] != " " or not v[5:7].isalpha()):
24
  raise ValueError("Invalid postal code format. It must be '1234 AA'.")
25
  return v
26
+
27
  def construct_query(self) -> str:
28
  """Constructs the query string based on provided inputs."""
29
  if self.postal_code and self.house_number:
 
33
  else:
34
  return ""
35
 
36
+ # Create a requests session for reuse
37
+ session = requests.Session()
38
+
39
+ @functools.lru_cache(maxsize=128)
40
+ def _fetch_cbs_data(postal_code: str, house_number: str, year: str):
41
+ """Helper function to fetch CBS data for a specific year (with caching)."""
42
+ url = f"https://service.pdok.nl/cbs/wijkenbuurten/2021/wfs?request=GetFeature&service=WFS&version=1.1.0&typeName=cbs_buurten_2021&outputFormat=json&srsName=EPSG:4326&CQL_FILTER=(postcode='{postal_code}')AND(huisnummer={house_number})"
43
+ try:
44
+ response = session.get(url)
45
+ response.raise_for_status() # Raise HTTPError for bad responses (4xx or 5xx)
46
+ data = response.json()
47
+ # Extract relevant data - adapt field names as needed
48
+ if data["features"]:
49
+ return data["features"][0]["properties"]
50
+ else:
51
+ return None # Or raise a custom exception if no features are found
52
+
53
+ except requests.exceptions.RequestException as e:
54
+ print(f"Error fetching CBS data for {year}: {e}") # Log the error
55
+ return None
56
+ except (ValueError, KeyError) as e:
57
+ print(f"Error parsing CBS data for {year}: {e}")
58
+ return None
59
+
60
+ @tool
61
+ def get_cbs_data(postal_code: str, house_number: str) -> str:
62
+ """
63
+ Retrieves CBS (Statistics Netherlands) demographic and facility data for a given postal code and house number.
64
+ Fetches data for 2021.
65
+
66
+ Args:
67
+ postal_code: The postal code (e.g., "1234AB").
68
+ house_number: The house number (e.g., "12").
69
+
70
+ Returns:
71
+ A JSON string containing the CBS data, or an error message if the data cannot be retrieved.
72
+ """
73
+ # Format inputs
74
+ formatted_postal_code = postal_code.replace(" ", "").upper()
75
+ formatted_house_number = house_number.strip()
76
+
77
+ data_2021 = _fetch_cbs_data(formatted_postal_code, formatted_house_number, "2021")
78
+
79
+ if data_2021:
80
+ # Create the dictionary to match the desired output format, including *all* fields, handling potential missing data.
81
+ cbs_data = {
82
+ "p2021_amount_of_inhabitants": data_2021.get("aantal_inwoners"),
83
+ "p2021_amount_of_men": data_2021.get("aantal_mannen"),
84
+ "p2021_amount_of_women": data_2021.get("aantal_vrouwen"),
85
+ "p2021_amount_of_inhabitants_0_to_15_year": data_2021.get("aantal_inwoners_0_tot_15_jaar"),
86
+ "p2021_amount_of_inhabitants_15_to_25_year": data_2021.get("aantal_inwoners_15_tot_25_jaar"),
87
+ "p2021_amount_of_inhabitants_25_to_45_year": data_2021.get("aantal_inwoners_25_tot_45_jaar"),
88
+ "p2021_amount_of_inhabitants_45_to_65_year": data_2021.get("aantal_inwoners_45_tot_65_jaar"),
89
+ "p2021_amount_of_inhabitants_65_years_and_older": data_2021.get("aantal_inwoners_65_jaar_en_ouder"),
90
+ "p2021_nearest_supermarket_distance": data_2021.get("dichtstbijzijnde_grote_supermarkt_afstand_in_km"),
91
+ "p2021_supermarkets_within_1km": data_2021.get("grote_supermarkt_aantal_binnen_1_km"),
92
+ "p2021_supermarkets_within_3km": data_2021.get("grote_supermarkt_aantal_binnen_3_km"),
93
+ "p2021_supermarkets_within_5km": data_2021.get("grote_supermarkt_aantal_binnen_5_km"),
94
+ "p2021_nearest_daily_grocery_store_distance": data_2021.get("dichtstbijzijnde_winkels_ov_dagel_levensm_afst_in_km"),
95
+ "p2021_daily_grocery_stores_within_1km": data_2021.get("winkels_ov_dagel_levensm_aantal_binnen_1_km"),
96
+ "p2021_daily_grocery_stores_within_3km": data_2021.get("winkels_ov_dagel_levensm_aantal_binnen_3_km"),
97
+ "p2021_daily_grocery_stores_within_5km": data_2021.get("winkels_ov_dagel_levensm_aantal_binnen_5_km"),
98
+ "p2021_nearest_department_store_distance": data_2021.get("dichtstbijzijnde_warenhuis_afstand_in_km"),
99
+ "p2021_department_stores_within_5km": data_2021.get("warenhuis_aantal_binnen_5_km"),
100
+ "p2021_department_stores_within_10km": data_2021.get("warenhuis_aantal_binnen_10_km"),
101
+ "p2021_department_stores_within_20km": data_2021.get("warenhuis_aantal_binnen_20_km"),
102
+ "p2021_nearest_pub_distance": data_2021.get("dichtstbijzijnde_cafe_afstand_in_km"),
103
+ "p2021_pubs_within_1km": data_2021.get("cafe_aantal_binnen_1_km"),
104
+ "p2021_pubs_within_3km": data_2021.get("cafe_aantal_binnen_3_km"),
105
+ "p2021_pubs_within_5km": data_2021.get("cafe_aantal_binnen_5_km"),
106
+ "p2021_nearest_cafeteria_distance": data_2021.get("dichtstbijzijnde_cafetaria_afstand_in_km"),
107
+ "p2021_cafeterias_within_1km": data_2021.get("cafetaria_aantal_binnen_1_km"),
108
+ "p2021_cafeterias_within_3km": data_2021.get("cafetaria_aantal_binnen_3_km"),
109
+ "p2021_cafeterias_within_5km": data_2021.get("cafetaria_aantal_binnen_5_km"),
110
+ "p2021_nearest_hotel_distance": data_2021.get("dichtstbijzijnde_hotel_afstand_in_km"),
111
+ "p2021_hotels_within_5km": data_2021.get("hotel_aantal_binnen_5_km"),
112
+ "p2021_hotels_within_10km": data_2021.get("hotel_aantal_binnen_10_km"),
113
+ "p2021_hotels_within_20km": data_2021.get("hotel_aantal_binnen_20_km"),
114
+ "p2021_nearest_restaurant_distance": data_2021.get("dichtstbijzijnde_restaurant_afstand_in_km"),
115
+ "p2021_restaurants_within_1km": data_2021.get("restaurant_aantal_binnen_1_km"),
116
+ "p2021_restaurants_within_3km": data_2021.get("restaurant_aantal_binnen_3_km"),
117
+ "p2021_restaurants_within_5km": data_2021.get("restaurant_aantal_binnen_5_km"),
118
+ "p2021_nearest_after_school_care_distance": data_2021.get("dichtstbijzijnde_buitenschoolse_opvang_afstand_in_km"),
119
+ "p2021_after_school_care_within_1km": data_2021.get("buitenschoolse_opvang_aantal_binnen_1_km"),
120
+ "p2021_after_school_care_within_3km": data_2021.get("buitenschoolse_opvang_aantal_binnen_3_km"),
121
+ "p2021_after_school_care_within_5km": data_2021.get("buitenschoolse_opvang_aantal_binnen_5_km"),
122
+ "p2021_nearest_day_care_distance": data_2021.get("dichtstbijzijnde_kinderdagverblijf_afstand_in_km"),
123
+ "p2021_day_care_within_1km": data_2021.get("kinderdagverblijf_aantal_binnen_1_km"),
124
+ "p2021_day_care_within_3km": data_2021.get("kinderdagverblijf_aantal_binnen_3_km"),
125
+ "p2021_day_care_within_5km": data_2021.get("kinderdagverblijf_aantal_binnen_5_km"),
126
+ "p2021_nearest_fire_station_distance": data_2021.get("dichtstbijzijnde_brandweerkazerne_afstand_in_km"),
127
+ "p2021_nearest_highway_access_distance": data_2021.get("dichtstbijzijnde_oprit_hoofdverkeersweg_afstand_in_km"),
128
+ "p2021_nearest_transfer_station_distance": data_2021.get("dichtstbijzijnde_overstapstation_afstand_in_km"),
129
+ "p2021_nearest_train_station_distance": data_2021.get("dichtstbijzijnde_treinstation_afstand_in_km"),
130
+ "p2021_nearest_theme_park_distance": data_2021.get("dichtstbijzijnde_attractiepark_afstand_in_km"),
131
+ "p2021_theme_parks_within_10km": data_2021.get("attractiepark_aantal_binnen_10_km"),
132
+ "p2021_theme_parks_within_20km": data_2021.get("attractiepark_aantal_binnen_20_km"),
133
+ "p2021_theme_parks_within_50km": data_2021.get("attractiepark_aantal_binnen_50_km"),
134
+ "p2021_nearest_cinema_distance": data_2021.get("dichtstbijzijnde_bioscoop_afstand_in_km"),
135
+ "p2021_cinemas_within_5km": data_2021.get("bioscoop_aantal_binnen_5_km"),
136
+ "p2021_cinemas_within_10km": data_2021.get("bioscoop_aantal_binnen_10_km"),
137
+ "p2021_cinemas_within_20km": data_2021.get("bioscoop_aantal_binnen_20_km"),
138
+ "p2021_nearest_museum_distance": data_2021.get("dichtstbijzijnde_museum_afstand_in_km"),
139
+ "p2021_museums_within_5km": data_2021.get("museum_aantal_binnen_5_km"),
140
+ "p2021_museums_within_10km": data_2021.get("museum_aantal_binnen_10_km"),
141
+ "p2021_museums_within_20km": data_2021.get("museum_aantal_binnen_20_km"),
142
+ "p2021_nearest_theater_distance": data_2021.get("dichtstbijzijnde_theater_afstand_in_km"),
143
+ "p2021_theaters_within_5km": data_2021.get("theater_aantal_binnen_5_km"),
144
+ "p2021_theaters_within_10km": data_2021.get("theater_aantal_binnen_10_km"),
145
+ "p2021_theaters_within_20km": data_2021.get("theater_aantal_binnen_20_km"),
146
+ "p2021_nearest_library_distance": data_2021.get("dichtstbijzijnde_bibliotheek_afstand_in_km"),
147
+ "p2021_nearest_ice_rink_distance": data_2021.get("dichtstbijzijnde_kunstijsbaan_afstand_in_km"),
148
+ "p2021_nearest_music_venue_distance": data_2021.get("dichtstbijzijnde_poppodium_afstand_in_km"),
149
+ "p2021_nearest_sauna_distance": data_2021.get("dichtstbijzijnde_sauna_afstand_in_km"),
150
+ "p2021_nearest_tanning_salon_distance": data_2021.get("dichtstbijzijnde_zonnebank_afstand_in_km"),
151
+ "p2021_nearest_swimming_pool_distance": data_2021.get("dichtstbijzijnde_zwembad_afstand_in_km"),
152
+ "p2021_nearest_primary_school_distance": data_2021.get("dichtstbijzijnde_basisonderwijs_afstand_in_km"),
153
+ "p2021_primary_schools_within_1km": data_2021.get("basisonderwijs_aantal_binnen_1_km"),
154
+ "p2021_primary_schools_within_3km": data_2021.get("basisonderwijs_aantal_binnen_3_km"),
155
+ "p2021_primary_schools_within_5km": data_2021.get("basisonderwijs_aantal_binnen_5_km"),
156
+ "p2021_nearest_havovwo_distance": data_2021.get("dichtstbijzijnde_havo_vwo_afstand_in_km"),
157
+ "p2021_havovwo_within_3km": data_2021.get("havo_vwo_aantal_binnen_3_km"),
158
+ "p2021_havovwo_within_5km": data_2021.get("havo_vwo_aantal_binnen_5_km"),
159
+ "p2021_havovwo_within_10km": data_2021.get("havo_vwo_aantal_binnen_10_km"),
160
+ "p2021_nearest_vmbo_distance": data_2021.get("dichtstbijzijnde_vmbo_afstand_in_km"),
161
+ "p2021_vmbo_within_3km": data_2021.get("vmbo_aantal_binnen_3_km"),
162
+ "p2021_vmbo_within_5km": data_2021.get("vmbo_aantal_binnen_5_km"),
163
+ "p2021_vmbo_within_10km": data_2021.get("vmbo_aantal_binnen_10_km"),
164
+ "p2021_nearest_secondary_school_distance": data_2021.get("dichtstbijzijnde_voortgezet_onderwijs_afstand_in_km"),
165
+ "p2021_secondary_schools_within_3km": data_2021.get("voortgezet_onderwijs_aantal_binnen_3_km"),
166
+ "p2021_secondary_schools_within_5km": data_2021.get("voortgezet_onderwijs_aantal_binnen_5_km"),
167
+ "p2021_secondary_schools_within_10km": data_2021.get("voortgezet_onderwijs_aantal_binnen_10_km"),
168
+ "p2021_nearest_gp_distance": data_2021.get("dichtstbijzijnde_huisartsenpraktijk_afstand_in_km"),
169
+ "p2021_gps_within_1km": data_2021.get("huisartsenpraktijk_aantal_binnen_1_km"),
170
+ "p2021_gps_within_3km": data_2021.get("huisartsenpraktijk_aantal_binnen_3_km"),
171
+ "p2021_gps_within_5km": data_2021.get("huisartsenpraktijk_aantal_binnen_5_km"),
172
+ "p2021_nearest_hospital_excl_outpatient_distance": data_2021.get("dichtstbijzijnde_ziekenh_excl_buitenpoli_afst_in_km"),
173
+ "p2021_hospitals_excl_outpatient_within_5km": data_2021.get("ziekenhuis_excl_buitenpoli_aantal_binnen_5_km"),
174
+ "p2021_hospitals_excl_outpatient_within_10km": data_2021.get("ziekenhuis_excl_buitenpoli_aantal_binnen_10_km"),
175
+ "p2021_hospitals_excl_outpatient_within_20km": data_2021.get("ziekenhuis_excl_buitenpoli_aantal_binnen_20_km"),
176
+ "p2021_nearest_hospital_incl_outpatient_distance": data_2021.get("dichtstbijzijnde_ziekenh_incl_buitenpoli_afst_in_km"),
177
+ "p2021_hospitals_incl_outpatient_within_5km": data_2021.get("ziekenhuis_incl_buitenpoli_aantal_binnen_5_km"),
178
+ "p2021_hospitals_incl_outpatient_within_10km": data_2021.get("ziekenhuis_incl_buitenpoli_aantal_binnen_10_km"),
179
+ "p2021_hospitals_incl_outpatient_within_20km": data_2021.get("ziekenhuis_incl_buitenpoli_aantal_binnen_20_km"),
180
+ "p2021_nearest_pharmacy_distance": data_2021.get("dichtstbijzijnde_apotheek_afstand_in_km"),
181
+ "p2021_nearest_gp_post_distance": data_2021.get("dichtstbijzijnde_huisartsenpost_afstand_in_km"),
182
+ }
183
+ return json.dumps(cbs_data) # Return as JSON string
184
+
185
+ else:
186
+ return json.dumps({"error": "Could not retrieve CBS data."})
187
+
188
 
189
+ @functools.lru_cache(maxsize=128) # Add caching
190
  @tool
191
  def pdok_location_info(postal_code: Optional[str] = None, house_number: Optional[str] = None, street_name: Optional[str] = None, city: Optional[str] = None) -> str:
192
+ """Provides information about a Dutch address or postal code, including a Google Maps link and CBS data.
193
+
194
  Args:
195
  postal_code: Postal code in the format '1234 AA'.
196
  house_number: House number of the address.
 
198
  city: Name of the city.
199
 
200
  Returns:
201
+ str: JSON string containing the location information, including a Google Maps link and CBS data, or an error message.
202
  """
203
+
204
  debug_info = []
205
  debug_info.append(f"Input values:\n"
206
  f" Postal code: {postal_code}\n"
207
  f" House number: {house_number}\n"
208
  f" Street name: {street_name}\n"
209
  f" City: {city}")
210
+
211
  base_url = "https://api.pdok.nl/bzk/locatieserver/search/v3_1/free"
212
  headers = {"accept": "application/json"}
213
+
214
  input_data = PDOKLocationSearchInput(postal_code=postal_code, house_number=house_number, street_name=street_name, city=city)
215
  query_string = input_data.construct_query()
216
 
 
222
  params = {
223
  "q": query_string,
224
  "fl": "*",
225
+ "fq": "type:(gemeente OR woonplaats OR weg OR postcode OR adres)",
226
  "df": "tekst",
227
+ "bq": "type:provincie^1.5",
228
  "bq": "type:gemeente^1.5",
229
  "bq": "type:woonplaats^1.5",
230
+ "bq": "type:weg^1.5",
231
  "bq": "type:postcode^0.5",
232
  "bq": "type:adres^1",
233
  "start": 0,
234
+ "rows": 1, # Reduced to 1
235
  "sort": "score desc,sortering asc,weergavenaam asc",
236
  "wt": "json",
237
  }
238
+
239
  try:
240
+ response = session.get(base_url, params=params, headers=headers) # Use the session
241
  debug_info.append(f"Response status code: {response.status_code}")
242
+
243
  response.raise_for_status()
244
  data = response.json()
245
+
246
  docs = data.get("response", {}).get("docs", [])
247
  debug_info.append(f"Number of docs found: {len(docs)}")
248
+
249
  if not docs:
250
  return f"Error: No results found\nDebug info:\n" + "\n".join(debug_info)
251
 
252
  first_result = docs[0]
253
  debug_info.append(f"First result data: {first_result}")
254
+
 
255
  location_info = {
256
  "straatnaam": first_result.get("straatnaam", ""),
257
  "huisnummer": first_result.get("huisnummer", ""),
 
265
  "centroide_rd": first_result.get("centroide_rd", "")
266
  }
267
 
 
268
  centroide_ll = location_info.get('centroide_ll')
269
  if centroide_ll:
270
  lon, lat = centroide_ll.replace("POINT(", "").replace(")", "").split()
271
  location_info["google_maps_url"] = f"https://www.google.com/maps/search/?api=1&query={lat},{lon}"
272
+
273
+ # --- Get CBS Data ---
274
+ if location_info["postcode"] and location_info["huisnummer"]:
275
+ cbs_data_str = get_cbs_data(location_info["postcode"], str(location_info["huisnummer"]))
276
+ try:
277
+ cbs_data = json.loads(cbs_data_str)
278
+ # Check for error in CBS data
279
+ if "error" in cbs_data:
280
+ location_info["cbs_data_error"] = cbs_data["error"] # Add error message.
281
+ else:
282
+ location_info.update(cbs_data) # Merge CBS data
283
+ except json.JSONDecodeError:
284
+ location_info["cbs_data_error"] = "Failed to parse CBS data."
285
+ else:
286
+ location_info["cbs_data_error"] = "Postcode or house number missing, cannot fetch CBS data."
287
+
288
+
289
+ return json.dumps(location_info)
290
+
291
  except requests.exceptions.RequestException as e:
292
  return f"Error during API request: {e}\nDebug info:\n" + "\n".join(debug_info)
293
  except (ValueError, KeyError) as e:
294
  return f"Error processing API response: {e}\nDebug info:\n" + "\n".join(debug_info)
295
+ except Exception as e:
296
+ return f"An unexpected error occurred: {e}\nDebug info:\n" + "\n".join(debug_info)
297
 
298
  @tool
299
+ def my_custom_tool(arg1:str, arg2:int)-> str:
 
300
  """A tool that does nothing yet
301
  Args:
302
  arg1: the first argument
 
311
  timezone: A string representing a valid timezone (e.g., 'America/New_York').
312
  """
313
  try:
 
314
  tz = pytz.timezone(timezone)
 
315
  local_time = datetime.datetime.now(tz).strftime("%Y-%m-%d %H:%M:%S")
316
  return f"The current local time in {timezone} is: {local_time}"
317
  except Exception as e:
318
  return f"Error fetching time for timezone '{timezone}': {str(e)}"
319
 
 
320
  final_answer = FinalAnswerTool()
321
 
 
 
 
322
  model = HfApiModel(
323
+ max_tokens=2096,
324
+ temperature=0.5,
325
+ model_id='Qwen/Qwen2.5-Coder-32B-Instruct',
326
+ custom_role_conversions=None,
327
  )
328
 
 
 
329
  image_generation_tool = load_tool("agents-course/text-to-image", trust_remote_code=True)
330
 
331
  with open("prompts.yaml", 'r') as stream:
332
  prompt_templates = yaml.safe_load(stream)
333
+
334
  agent = CodeAgent(
335
  model=model,
336
+ tools=[final_answer, get_current_time_in_timezone, pdok_location_info, get_cbs_data], # Include get_cbs_data
337
+ max_steps=5, # Tune this value! Start low.
338
+ verbosity_level=0, # Set to 0 for production
339
  grammar=None,
340
  planning_interval=None,
341
  name=None,
 
343
  prompt_templates=prompt_templates
344
  )
345
 
 
346
  GradioUI(agent).launch()