celikn commited on
Commit
d135896
·
1 Parent(s): 31c9e69

map interactive poi eklendi

Browse files
Files changed (1) hide show
  1. app.py +153 -330
app.py CHANGED
@@ -1,329 +1,130 @@
1
  import os
 
2
  import gradio as gr
3
- import geopandas as gpd
4
- import folium
5
-
6
- # osmnx isteğe bağlı (fallback için)
7
- try:
8
- import osmnx as ox
9
- except ImportError:
10
- ox = None
11
-
12
  from huggingface_hub import InferenceClient, login
13
 
14
- # ================
15
- # HF TOKEN & MODEL
16
- # ================
17
  HF_TOKEN = (os.environ.get("HUGGINGFACE_HUB_TOKEN", "") or "").strip()
 
18
  if HF_TOKEN:
19
  login(token=HF_TOKEN)
20
  else:
21
- print("UYARI: HUGGINGFACE_HUB_TOKEN bulunamadı, kamuya açık modellerle sınırlı olabilirsiniz.")
22
 
 
23
  client = InferenceClient(
24
  model="openai/gpt-oss-20b",
25
- token=HF_TOKEN if HF_TOKEN else None,
26
  )
27
 
28
- # =========================
29
- # ÖNCEDEN HAZIRLANMIŞ OSM VERİSİ
30
- # =========================
31
- NEIGH_PATH = "data/neighborhoods.geojson"
32
- POIS_PATH = "data/pois.geojson"
33
-
34
- if not (os.path.exists(NEIGH_PATH) and os.path.exists(POIS_PATH)):
35
- print("UYARI: data/ klasöründe neighborhoods.geojson / pois.geojson bulunamadı!")
36
- neighborhoods_gdf = None
37
- pois_gdf = None
38
- else:
39
- neighborhoods_gdf = gpd.read_file(NEIGH_PATH)
40
- pois_gdf = gpd.read_file(POIS_PATH)
41
- print(f"{len(neighborhoods_gdf)} mahalle/semt, {len(pois_gdf)} POI yüklendi.")
42
-
43
-
44
- DEFAULT_TAGS = {
45
- "amenity": ["school", "pharmacy", "hospital", "restaurant", "cafe", "bank"],
46
- "leisure": ["park", "playground"],
47
- "shop": True,
48
- }
49
-
50
-
51
- # =========================
52
- # OSM / CBS FONKSİYONLARI
53
- # =========================
54
- def get_neighborhood_gdf(city: str, neighborhood: str):
55
- if neighborhoods_gdf is not None:
56
- mask = (
57
- (neighborhoods_gdf["city"] == city)
58
- & (neighborhoods_gdf["neighborhood"] == neighborhood)
59
- )
60
- gdf_local = neighborhoods_gdf[mask]
61
- if gdf_local is not None and len(gdf_local) > 0:
62
- return gdf_local
63
-
64
- if ox is None:
65
- print("OSM fallback kullanılamıyor: osmnx yüklü değil.")
66
- return None
67
-
68
- query = f"{neighborhood}, {city}, Türkiye"
69
- print(f"OSM fallback: {query}")
70
- try:
71
- gdf_osm = ox.geocode_to_gdf(query)
72
- except Exception as e:
73
- print("Mahalle geocode hatası (OSM fallback):", e)
74
- return None
75
-
76
- if gdf_osm is None or len(gdf_osm) == 0:
77
- return None
78
-
79
- gdf_osm = gdf_osm.copy()
80
- gdf_osm["city"] = city
81
- gdf_osm["neighborhood"] = neighborhood
82
- return gdf_osm
83
-
84
-
85
- def get_pois_within(gdf, tags=None):
86
- if gdf is None:
87
- return None
88
-
89
- if tags is None:
90
- tags = DEFAULT_TAGS
91
-
92
- if pois_gdf is not None and "city" in gdf.columns and "neighborhood" in gdf.columns:
93
- row = gdf.iloc[0]
94
- city = row["city"]
95
- neighborhood = row["neighborhood"]
96
-
97
- mask = (
98
- (pois_gdf["city"] == city)
99
- & (pois_gdf["neighborhood"] == neighborhood)
100
- )
101
- pois_local = pois_gdf[mask]
102
-
103
- if pois_local is not None and len(pois_local) > 0:
104
- return pois_local
105
 
106
- if ox is None:
107
- print("OSM POI fallback kullanılamıyor: osmnx yüklü değil.")
108
- return None
109
 
110
- try:
111
- polygon = gdf.geometry.iloc[0]
112
- pois_osm = ox.features_from_polygon(polygon, tags)
113
- return pois_osm
114
- except Exception as e:
115
- print("POI hatası (OSM fallback):", e)
116
  return None
117
 
 
 
118
 
119
- def summarize_pois(gdf, pois):
120
- summary = {}
121
-
122
- try:
123
- area_m2 = gdf.to_crs(epsg=3857).geometry.iloc[0].area
124
- summary["alan_m2"] = float(area_m2)
125
- summary["alan_km2"] = float(area_m2 / 1_000_000)
126
- except Exception as e:
127
- print("Alan hesaplama hatası:", e)
128
- summary["alan_m2"] = None
129
- summary["alan_km2"] = None
130
-
131
- if pois is None or len(pois) == 0:
132
- summary["toplam_poi"] = 0
133
- return summary
134
 
135
- summary["toplam_poi"] = int(len(pois))
 
 
 
136
 
137
- if "amenity" in pois.columns:
138
- for k, v in pois["amenity"].value_counts().to_dict().items():
139
- summary[f"amenity_{k}"] = int(v)
140
 
141
- if "leisure" in pois.columns:
142
- for k, v in pois["leisure"].value_counts().to_dict().items():
143
- summary[f"leisure_{k}"] = int(v)
144
 
145
- if "shop" in pois.columns:
146
- for k, v in pois["shop"].value_counts().to_dict().items():
147
- summary[f"shop_{k}"] = int(v)
 
 
 
 
 
 
 
 
148
 
149
- return summary
 
150
 
 
 
 
151
 
152
- def build_stats_text(summary: dict) -> str:
153
- if not summary:
154
- return "Veri bulunamadı."
 
 
 
155
 
156
- alan = summary.get("alan_km2", 0) or 0.0
157
- toplam_poi = summary.get("toplam_poi", 0)
158
- okul = summary.get("amenity_school", 0)
159
- park = summary.get("leisure_park", 0)
160
- eczane = summary.get("amenity_pharmacy", 0)
161
- cafe = summary.get("amenity_cafe", 0)
162
- restoran = summary.get("amenity_restaurant", 0)
 
 
163
 
164
- lines = [
165
- f"- Tahmini alan: {alan:.2f} km²",
166
- f"- Toplam POI (ilgi noktası): {toplam_poi}",
167
- f"- Okul sayısı: {okul}",
168
- f"- Park sayısı: {park}",
169
- f"- Eczane sayısı: {eczane}",
170
- f"- Kafe sayısı: {cafe}",
171
- f"- Restoran sayısı: {restoran}",
172
- ]
173
- return "\n".join(lines)
174
 
175
 
176
- def create_map(gdf, pois):
177
- """
178
- Mahalle poligonu + POI noktalarını, veri tipine göre
179
- farklı katman ve renklerde gösteren Folium haritası.
180
- """
181
- try:
182
- polygon = gdf.geometry.iloc[0]
183
- centroid = polygon.centroid
184
-
185
- m = folium.Map(location=[centroid.y, centroid.x], zoom_start=15)
186
-
187
- # --- Mahalle poligonu (tek katman) ---
188
- folium.GeoJson(
189
- gdf.geometry.__geo_interface__,
190
- name="Mahalle"
191
- ).add_to(m)
192
-
193
- # POI yoksa direkt döndür
194
- if pois is None or len(pois) == 0:
195
- folium.LayerControl().add_to(m)
196
- return m._repr_html_()
197
-
198
- # Sadece nokta geometriler
199
- pois_points = pois[pois.geometry.type == "Point"].copy()
200
- if len(pois_points) == 0:
201
- folium.LayerControl().add_to(m)
202
- return m._repr_html_()
203
-
204
- # -------------------------
205
- # KATMAN / RENK TANIMLARI
206
- # -------------------------
207
- layer_defs = [
208
- ("Okullar", ("amenity", "school"), "blue"),
209
- ("Hastaneler", ("amenity", "hospital"), "red"),
210
- ("Eczaneler", ("amenity", "pharmacy"), "darkred"),
211
- ("Kafeler", ("amenity", "cafe"), "purple"),
212
- ("Restoranlar", ("amenity", "restaurant"), "orange"),
213
- ("Bankalar", ("amenity", "bank"), "darkblue"),
214
- ("Parklar", ("leisure", "park"), "green"),
215
- ("Oyun Alanları",("leisure", "playground"), "lightgreen"),
216
- ("Dükkanlar", ("shop", None), "cadetblue"),
217
- ]
218
-
219
- used_indexes = set()
220
-
221
- for layer_name, (col, value), color in layer_defs:
222
- if col not in pois_points.columns:
223
- continue
224
-
225
- if value is None:
226
- mask = pois_points[col].notna()
227
- else:
228
- mask = (pois_points[col] == value)
229
-
230
- layer_gdf = pois_points[mask]
231
- if layer_gdf.empty:
232
- continue
233
-
234
- fg = folium.FeatureGroup(name=layer_name, show=True)
235
-
236
- for idx, row in layer_gdf.iterrows():
237
- used_indexes.add(idx)
238
- lon, lat = row.geometry.x, row.geometry.y
239
-
240
- # name kolonunda NaN / sayı vs. olabilir → str'e çevir
241
- raw_name = row.get("name", layer_name[:-1] if layer_name.endswith("lar") else "POI")
242
- name = str(raw_name) if raw_name is not None else "POI"
243
-
244
- popup_lines = [name]
245
-
246
- # biraz daha bilgi ekleyelim – hepsini str'e çeviriyoruz
247
- if "amenity" in row and isinstance(row["amenity"], str):
248
- popup_lines.append(f"amenity: {row['amenity']}")
249
- if "leisure" in row and isinstance(row["leisure"], str):
250
- popup_lines.append(f"leisure: {row['leisure']}")
251
- if "shop" in row and isinstance(row["shop"], str):
252
- popup_lines.append(f"shop: {row['shop']}")
253
-
254
- # HER ŞEYİN string olduğundan emin ol
255
- popup_lines = [str(x) for x in popup_lines]
256
- popup_text = "<br>".join(popup_lines)
257
-
258
- folium.CircleMarker(
259
- location=[lat, lon],
260
- radius=4,
261
- color=color,
262
- fill=True,
263
- fill_opacity=0.8,
264
- popup=folium.Popup(popup_text, max_width=250),
265
- ).add_to(fg)
266
-
267
- fg.add_to(m)
268
-
269
- # Diğer POI'ler
270
- others = pois_points[~pois_points.index.isin(used_indexes)]
271
- if not others.empty:
272
- fg_other = folium.FeatureGroup(name="Diğer POI'ler", show=False)
273
- for _, row in others.iterrows():
274
- lon, lat = row.geometry.x, row.geometry.y
275
- raw_name = row.get("name", "POI")
276
- name = str(raw_name) if raw_name is not None else "POI"
277
- folium.CircleMarker(
278
- location=[lat, lon],
279
- radius=3,
280
- color="gray",
281
- fill=True,
282
- fill_opacity=0.6,
283
- popup=name,
284
- ).add_to(fg_other)
285
- fg_other.add_to(m)
286
-
287
- folium.LayerControl().add_to(m)
288
- return m._repr_html_()
289
-
290
- except Exception as e:
291
- msg = f"Harita oluşturulurken hata oluştu: {repr(e)}"
292
- print("HARITA HATASI:", msg)
293
- return f"<pre>{msg}</pre>"
294
-
295
-
296
-
297
- # =========================
298
- # GRADIO YARDIMCI FONKSİYONLARI
299
- # =========================
300
- def load_osm_context(city, neighborhood):
301
- """
302
- Butona basıldığında:
303
- - mahalle çokgenini bul
304
- - POI'leri al
305
- - özet çıkar
306
- - harita HTML + LLM için bağlam döndür
307
- """
308
- if not city or not neighborhood:
309
- return "<b>Lütfen şehir ve mahalle girin.</b>", "Şehir/mahalle girilmedi.", ""
310
-
311
- gdf = get_neighborhood_gdf(city.strip(), neighborhood.strip())
312
- if gdf is None or len(gdf) == 0:
313
- return "<b>Bu mahalle bulunamadı.</b>", "Bu mahalle için veri bulunamadı.", ""
314
-
315
- pois = get_pois_within(gdf)
316
- summary = summarize_pois(gdf, pois)
317
- stats_text = build_stats_text(summary)
318
- map_html = create_map(gdf, pois)
319
-
320
- # LLM için bağlam:
321
- llm_context = (
322
- f"Şehir: {city}, Mahalle: {neighborhood}\n"
323
- f"Bu mahalle için sayısal özet:\n{stats_text}"
324
- )
325
- return map_html, stats_text, llm_context
326
-
327
  def respond(
328
  message,
329
  history,
@@ -331,23 +132,34 @@ def respond(
331
  max_tokens,
332
  temperature,
333
  top_p,
334
- osm_context, # gr.State ile gelecek
335
  ):
336
- # OSM bağlamını sistem mesajına ekle
 
 
 
 
 
 
 
 
 
337
  full_system = system_message
338
- if osm_context:
339
  full_system += (
340
- "\n\nAşağıda, konuştuğumuz mahalleyle ilgili "
341
- "coğrafi ve POI istatistikleri var. "
342
- "Kullanıcı soru sorarsa bunlara dayanarak cevap ver:\n"
343
- f"{osm_context}"
344
  )
345
 
 
346
  messages = [{"role": "system", "content": full_system}]
347
  messages.extend(history)
348
  messages.append({"role": "user", "content": message})
349
 
350
  response = ""
 
 
351
  for chunk in client.chat_completion(
352
  messages=messages,
353
  max_tokens=max_tokens,
@@ -363,24 +175,28 @@ def respond(
363
  response += token_text
364
  yield response
365
 
366
- # =========================
367
- # GRADIO ARAYÜZÜ
368
- # =========================
 
369
  with gr.Blocks() as demo:
370
- gr.Markdown("## OSM Destekli Mahalle Sohbet Botu")
371
 
372
- # OSM bağlamını saklamak için state
373
- osm_state = gr.State("")
 
374
 
375
  with gr.Row():
376
- # Sol: Chat
377
  with gr.Column(scale=2):
378
  chatbot = gr.ChatInterface(
379
  respond,
380
  type="messages",
 
 
381
  additional_inputs=[
382
  gr.Textbox(
383
- value="Sen şehir planlama ve mahalleler hakkında bilgi veren yardımsever bir asistansın.",
384
  label="System message",
385
  ),
386
  gr.Slider(
@@ -391,8 +207,8 @@ with gr.Blocks() as demo:
391
  label="Max new tokens",
392
  ),
393
  gr.Slider(
394
- minimum=0.0,
395
- maximum=2.0, # <-- en fazla 2 olmalı modele gore
396
  value=0.7,
397
  step=0.1,
398
  label="Temperature",
@@ -404,32 +220,39 @@ with gr.Blocks() as demo:
404
  step=0.05,
405
  label="Top-p (nucleus sampling)",
406
  ),
407
- osm_state, # >>> buradan respond() içine gidiyor
408
  ],
409
  )
410
 
411
- # Sağ: Harita + parametreler
412
  with gr.Column(scale=1):
413
- gr.Markdown("### Mahalle Seçimi / Harita")
414
 
415
- city_in = gr.Textbox(label="Şehir", value="İstanbul")
416
- neigh_in = gr.Textbox(label="Mahalle / Semt", value="Kadıköy")
 
 
 
 
417
 
418
- load_btn = gr.Button("Haritayı Yükle")
 
 
 
 
 
419
 
420
- map_html = gr.HTML(label="Harita")
421
- stats_box = gr.Textbox(
422
- label="Mahalle Özeti (LLM Bağlamı)",
423
- lines=8,
424
  )
425
 
426
- # Buton: OSM verisini yükle, haritayı ve state'i güncelle
427
- load_btn.click(
428
- fn=load_osm_context,
429
- inputs=[city_in, neigh_in],
430
- outputs=[map_html, stats_box, osm_state],
431
  )
432
 
433
  if __name__ == "__main__":
434
  demo.launch()
435
-
 
1
  import os
2
+ import math
3
  import gradio as gr
 
 
 
 
 
 
 
 
 
4
  from huggingface_hub import InferenceClient, login
5
 
6
+ # ---- HF token & login integration ----
 
 
7
  HF_TOKEN = (os.environ.get("HUGGINGFACE_HUB_TOKEN", "") or "").strip()
8
+
9
  if HF_TOKEN:
10
  login(token=HF_TOKEN)
11
  else:
12
+ print("UYARI: HF_TOKEN / HUGGINGFACE_HUB_TOKEN bulunamadı, gated modellere erişilemeyebilir.")
13
 
14
+ # Create a single shared client (reuse across requests)
15
  client = InferenceClient(
16
  model="openai/gpt-oss-20b",
17
+ token=HF_TOKEN if HF_TOKEN else None, # will still work for public models without token
18
  )
19
 
20
+ # ==========================================
21
+ # ÖRNEK POI VERİSİ
22
+ # (BUNU KENDİ OSM / GEOJSON VERİNLE DEĞİŞTİREBİLİRSİN)
23
+ # ==========================================
24
+ POIS = [
25
+ {"name": "Kafemiz", "lat": 41.0380, "lon": 29.0000, "type": "cafe"},
26
+ {"name": "Parkımız", "lat": 41.0390, "lon": 29.0020, "type": "park"},
27
+ {"name": "Eczanemiz", "lat": 41.0375, "lon": 29.0010, "type": "pharmacy"},
28
+ ]
29
+
30
+ # Öneri:
31
+ # Kendi pois_gdf GeoDataFrame'inden şu şekilde liste üretebilirsin:
32
+ # POIS = [
33
+ # {
34
+ # "name": row.get("name", "POI"),
35
+ # "lat": row.geometry.y,
36
+ # "lon": row.geometry.x,
37
+ # "type": row.get("amenity") or row.get("leisure") or row.get("shop")
38
+ # }
39
+ # for _, row in pois_gdf.iterrows()
40
+ # ]
41
+
42
+
43
+ # ==========================================
44
+ # HARİTADA TIKLANAN NOKTAYA EN YAKIN POI'Yİ BULMA
45
+ # ==========================================
46
+ def haversine(lat1, lon1, lat2, lon2):
47
+ """Yaklaşık metre cinsinden mesafe (küçük alanlar için yeterli)."""
48
+ R = 6371000 # metre
49
+ dlat = math.radians(lat2 - lat1)
50
+ dlon = math.radians(lon2 - lon1)
51
+ a = (
52
+ math.sin(dlat / 2) ** 2
53
+ + math.cos(math.radians(lat1))
54
+ * math.cos(math.radians(lat2))
55
+ * math.sin(dlon / 2) ** 2
56
+ )
57
+ c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
58
+ return R * c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
 
 
 
 
60
 
61
+ def find_nearest_poi(click_lat, click_lon, pois, max_dist_m=300):
62
+ """
63
+ Tıklanan koordinata en yakın POI'yi bul.
64
+ max_dist_m üstünde ise None döndür.
65
+ """
66
+ if not pois:
67
  return None
68
 
69
+ best = None
70
+ best_dist = None
71
 
72
+ for poi in pois:
73
+ d = haversine(click_lat, click_lon, poi["lat"], poi["lon"])
74
+ if best is None or d < best_dist:
75
+ best = poi
76
+ best_dist = d
 
 
 
 
 
 
 
 
 
 
77
 
78
+ if best_dist is not None and best_dist <= max_dist_m:
79
+ best = dict(best) # orijinal listeyi bozmamak için kopya
80
+ best["distance_m"] = round(best_dist, 1)
81
+ return best
82
 
83
+ return None
 
 
84
 
 
 
 
85
 
86
+ # ==========================================
87
+ # HARİTA TIKLAMA CALLBACK'İ
88
+ # ==========================================
89
+ def on_map_click(map_value, poi_state):
90
+ """
91
+ map_value: gr.Map'in değeri.
92
+ mode="point" olduğunda genelde [lat, lon] olarak gelir.
93
+ poi_state: State içindeki POI listesi.
94
+ """
95
+ if not map_value or len(map_value) < 2:
96
+ return "Haritada geçerli bir nokta seçilemedi.", ""
97
 
98
+ click_lat, click_lon = map_value[0], map_value[1]
99
+ poi = find_nearest_poi(click_lat, click_lon, poi_state)
100
 
101
+ if poi is None:
102
+ info_text = "Yakında (örn. 300 m içinde) POI bulunamadı."
103
+ return info_text, ""
104
 
105
+ info_text = (
106
+ f"Seçilen POI:\n"
107
+ f"- Ad: {poi.get('name', 'Bilinmiyor')}\n"
108
+ f"- Tür: {poi.get('type', 'bilinmiyor')}\n"
109
+ f"- Uzaklık: {poi.get('distance_m', '?')} m"
110
+ )
111
 
112
+ # LLM bağlamı
113
+ poi_context = (
114
+ "Kullanıcı haritada bir POI seçti.\n"
115
+ f"Ad: {poi.get('name')}\n"
116
+ f"Tür: {poi.get('type')}\n"
117
+ f"Konum: (lat={poi.get('lat')}, lon={poi.get('lon')})\n"
118
+ f"Tıklama noktasına uzaklık: {poi.get('distance_m', '?')} m.\n"
119
+ "Kullanıcı bu yerle ilgili soru sorarsa bu bilgileri kullanarak cevap ver."
120
+ )
121
 
122
+ return info_text, poi_context
 
 
 
 
 
 
 
 
 
123
 
124
 
125
+ # ==========================================
126
+ # LLM SOHBET FONKSİYONU
127
+ # ==========================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  def respond(
129
  message,
130
  history,
 
132
  max_tokens,
133
  temperature,
134
  top_p,
135
+ poi_context, # <<< harita ile seçilen POI bağlamı buradan geliyor
136
  ):
137
+ """
138
+ Streaming chat using Hugging Face Inference API.
139
+ History is a list of {"role": "...", "content": "..."} dicts.
140
+ """
141
+
142
+ # Güvenli aralığa çek (model: max 2)
143
+ temperature = max(0.0, min(2.0, float(temperature)))
144
+ top_p = max(0.0, min(1.0, float(top_p)))
145
+
146
+ # System mesajına POI bağlamını ekle
147
  full_system = system_message
148
+ if poi_context:
149
  full_system += (
150
+ "\n\nAşağıda kullanıcının haritada seçtiği yer ile ilgili bilgiler var.\n"
151
+ "Kullanıcı bu yer hakkında soru sorarsa bu bağlamı kullanarak cevap ver:\n"
152
+ f"{poi_context}"
 
153
  )
154
 
155
+ # Build messages list
156
  messages = [{"role": "system", "content": full_system}]
157
  messages.extend(history)
158
  messages.append({"role": "user", "content": message})
159
 
160
  response = ""
161
+
162
+ # Stream tokens from the model
163
  for chunk in client.chat_completion(
164
  messages=messages,
165
  max_tokens=max_tokens,
 
175
  response += token_text
176
  yield response
177
 
178
+
179
+ # ==========================================
180
+ # GRADIO ARAYÜZÜ (SOL CHAT, SAĞ HARİTA)
181
+ # ==========================================
182
  with gr.Blocks() as demo:
183
+ gr.Markdown("## Haritada POI Seçen Basit Chat Botu")
184
 
185
+ # State'ler: POI listesi + seçilen POI bağlamı
186
+ poi_state = gr.State(POIS)
187
+ poi_context = gr.State("")
188
 
189
  with gr.Row():
190
+ # SOL SÜTUN: CHAT
191
  with gr.Column(scale=2):
192
  chatbot = gr.ChatInterface(
193
  respond,
194
  type="messages",
195
+ title="Basit Chat Botu",
196
+ description="Küçük bir sohbet botu, HF Inference API ile çalışıyor.",
197
  additional_inputs=[
198
  gr.Textbox(
199
+ value="You are a friendly Chatbot.",
200
  label="System message",
201
  ),
202
  gr.Slider(
 
207
  label="Max new tokens",
208
  ),
209
  gr.Slider(
210
+ minimum=0.0, # 0 olabilir
211
+ maximum=2.0, # model en fazla 2'yi destekliyor
212
  value=0.7,
213
  step=0.1,
214
  label="Temperature",
 
220
  step=0.05,
221
  label="Top-p (nucleus sampling)",
222
  ),
223
+ poi_context, # <<< respond() fonksiyonuna parametre olarak gidiyor
224
  ],
225
  )
226
 
227
+ # SAĞ SÜTUN: HARİTA
228
  with gr.Column(scale=1):
229
+ gr.Markdown("### Haritadan POI Seç")
230
 
231
+ # POI'lerin ortalama konumunu başlangıç merkezi olarak alalım
232
+ if POIS:
233
+ center_lat = sum(p["lat"] for p in POIS) / len(POIS)
234
+ center_lon = sum(p["lon"] for p in POIS) / len(POIS)
235
+ else:
236
+ center_lat, center_lon = 41.038, 29.0 # fallback: İstanbul civarı
237
 
238
+ # Kullanıcı tıklayınca [lat, lon] dönen interaktif harita
239
+ map_comp = gr.Map(
240
+ label="Harita",
241
+ value=[center_lat, center_lon],
242
+ interactive=True,
243
+ )
244
 
245
+ poi_info_box = gr.Textbox(
246
+ label="Seçilen POI Bilgisi",
247
+ lines=6,
 
248
  )
249
 
250
+ # Haritada tıklama -> on_map_click
251
+ map_comp.select(
252
+ fn=on_map_click,
253
+ inputs=[map_comp, poi_state],
254
+ outputs=[poi_info_box, poi_context],
255
  )
256
 
257
  if __name__ == "__main__":
258
  demo.launch()