Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -606,15 +606,15 @@ def create_comparison_map(gdf1, gdf2):
|
|
| 606 |
|
| 607 |
|
| 608 |
|
| 609 |
-
|
| 610 |
def run_overpass_to_map(query: str):
|
| 611 |
"""
|
| 612 |
-
Overpass QL sorgusunu çalıştırır
|
| 613 |
-
|
| 614 |
"""
|
| 615 |
-
query = normalize_overpass_query(query)
|
|
|
|
| 616 |
if not query or not query.strip():
|
| 617 |
-
return "<b>Overpass sorgusu boş.</b>"
|
| 618 |
|
| 619 |
url = "https://overpass-api.de/api/interpreter"
|
| 620 |
|
|
@@ -623,17 +623,16 @@ def run_overpass_to_map(query: str):
|
|
| 623 |
resp.raise_for_status()
|
| 624 |
data = resp.json()
|
| 625 |
except Exception as e:
|
| 626 |
-
|
| 627 |
try:
|
| 628 |
print("Overpass response text:", resp.text[:500])
|
| 629 |
except Exception:
|
| 630 |
pass
|
| 631 |
-
|
| 632 |
-
return f"<b>Overpass isteği hatası:</b> {e}"
|
| 633 |
|
| 634 |
elements = data.get("elements", [])
|
| 635 |
if not elements:
|
| 636 |
-
return "<b>Overpass sonucu: veri bulunamadı.</b>"
|
| 637 |
|
| 638 |
# Merkez için ilk noktanın koordinatlarını bulalım
|
| 639 |
center_lat, center_lon = None, None
|
|
@@ -642,7 +641,7 @@ def run_overpass_to_map(query: str):
|
|
| 642 |
center_lat, center_lon = el["lat"], el["lon"]
|
| 643 |
break
|
| 644 |
if center_lat is None:
|
| 645 |
-
return "<b>Overpass sonucu: nokta verisi yok.</b>"
|
| 646 |
|
| 647 |
m = folium.Map(location=[center_lat, center_lon], zoom_start=14)
|
| 648 |
|
|
@@ -690,8 +689,11 @@ def run_overpass_to_map(query: str):
|
|
| 690 |
).add_to(fg_ways)
|
| 691 |
|
| 692 |
folium.LayerControl().add_to(m)
|
| 693 |
-
return m._repr_html_()
|
| 694 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 695 |
|
| 696 |
|
| 697 |
|
|
@@ -716,6 +718,98 @@ def llm_overpass_to_map(natural_prompt: str, model_name: str):
|
|
| 716 |
map_html = run_overpass_to_map(query)
|
| 717 |
return query, map_html
|
| 718 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 719 |
|
| 720 |
|
| 721 |
|
|
@@ -732,6 +826,7 @@ def respond(
|
|
| 732 |
temperature,
|
| 733 |
top_p,
|
| 734 |
compare_context, # mahalle karşılaştırma bağlamı
|
|
|
|
| 735 |
):
|
| 736 |
|
| 737 |
|
|
@@ -791,6 +886,14 @@ def respond(
|
|
| 791 |
"Kullanıcı bu mahalleler hakkında soru sorarsa bu bağlama göre cevap ver:\n"
|
| 792 |
f"{compare_context}"
|
| 793 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 794 |
|
| 795 |
messages = [{"role": "system", "content": full_system}]
|
| 796 |
messages.extend(history)
|
|
@@ -820,6 +923,8 @@ with gr.Blocks() as demo:
|
|
| 820 |
gr.Markdown("## Mahalle Karşılaştırmalı Chat Botu")
|
| 821 |
|
| 822 |
compare_state = gr.State("")
|
|
|
|
|
|
|
| 823 |
|
| 824 |
with gr.Row():
|
| 825 |
# SOL SÜTUN: CHAT
|
|
@@ -837,7 +942,7 @@ with gr.Blocks() as demo:
|
|
| 837 |
"Qwen/Qwen2.5-72B-Instruct", # 72B
|
| 838 |
|
| 839 |
# Çok büyük model
|
| 840 |
-
"openai/gpt-oss-120b", #
|
| 841 |
],
|
| 842 |
label="Model Seç (Bu listedeki modeller Hugging Face Inference API chat_completion ile uyumludur)",
|
| 843 |
value="abacusai/Dracarys-72B-Instruct"
|
|
@@ -885,6 +990,8 @@ with gr.Blocks() as demo:
|
|
| 885 |
temperature_slider,
|
| 886 |
top_p_slider,
|
| 887 |
compare_state, # >>> mahalle karşılaştırma bağlamı
|
|
|
|
|
|
|
| 888 |
],
|
| 889 |
)
|
| 890 |
|
|
@@ -972,10 +1079,11 @@ with gr.Blocks() as demo:
|
|
| 972 |
run_overpass_btn.click(
|
| 973 |
fn=run_overpass_to_map,
|
| 974 |
inputs=[overpass_box],
|
| 975 |
-
outputs=[map_html],
|
| 976 |
)
|
| 977 |
|
| 978 |
|
|
|
|
| 979 |
compare_btn.click(
|
| 980 |
fn=prepare_comparison,
|
| 981 |
inputs=[city_in, district1_in, neigh1_in, district2_in, neigh2_in],
|
|
|
|
| 606 |
|
| 607 |
|
| 608 |
|
|
|
|
| 609 |
def run_overpass_to_map(query: str):
|
| 610 |
"""
|
| 611 |
+
Overpass QL sorgusunu çalıştırır, Folium haritası ve LLM bağlamı için
|
| 612 |
+
metinsel bir özet döndürür.
|
| 613 |
"""
|
| 614 |
+
query = normalize_overpass_query(query) if 'normalize_overpass_query' in globals() else query
|
| 615 |
+
|
| 616 |
if not query or not query.strip():
|
| 617 |
+
return "<b>Overpass sorgusu boş.</b>", "Geçerli bir Overpass sorgusu sağlanmadı."
|
| 618 |
|
| 619 |
url = "https://overpass-api.de/api/interpreter"
|
| 620 |
|
|
|
|
| 623 |
resp.raise_for_status()
|
| 624 |
data = resp.json()
|
| 625 |
except Exception as e:
|
| 626 |
+
print("Overpass isteği hatası:", e)
|
| 627 |
try:
|
| 628 |
print("Overpass response text:", resp.text[:500])
|
| 629 |
except Exception:
|
| 630 |
pass
|
| 631 |
+
return f"<b>Overpass isteği hatası:</b> {e}", "Overpass isteğinde hata oluştu, veri yok."
|
|
|
|
| 632 |
|
| 633 |
elements = data.get("elements", [])
|
| 634 |
if not elements:
|
| 635 |
+
return "<b>Overpass sonucu: veri bulunamadı.</b>", "Overpass sonucu: hiç element bulunamadı."
|
| 636 |
|
| 637 |
# Merkez için ilk noktanın koordinatlarını bulalım
|
| 638 |
center_lat, center_lon = None, None
|
|
|
|
| 641 |
center_lat, center_lon = el["lat"], el["lon"]
|
| 642 |
break
|
| 643 |
if center_lat is None:
|
| 644 |
+
return "<b>Overpass sonucu: nokta verisi yok.</b>", "Overpass sonucu: nokta verisi bulunamadı."
|
| 645 |
|
| 646 |
m = folium.Map(location=[center_lat, center_lon], zoom_start=14)
|
| 647 |
|
|
|
|
| 689 |
).add_to(fg_ways)
|
| 690 |
|
| 691 |
folium.LayerControl().add_to(m)
|
|
|
|
| 692 |
|
| 693 |
+
map_html = m._repr_html_()
|
| 694 |
+
summary_text = summarize_overpass_data(data)
|
| 695 |
+
|
| 696 |
+
return map_html, summary_text
|
| 697 |
|
| 698 |
|
| 699 |
|
|
|
|
| 718 |
map_html = run_overpass_to_map(query)
|
| 719 |
return query, map_html
|
| 720 |
|
| 721 |
+
def summarize_overpass_data(data: dict, max_examples: int = 30) -> str:
|
| 722 |
+
"""
|
| 723 |
+
Overpass JSON sonucundan LLM'e verilecek metinsel bir özet üretir.
|
| 724 |
+
Çok büyük verilerde token patlamaması için sınırlı örnek verir.
|
| 725 |
+
"""
|
| 726 |
+
if not data:
|
| 727 |
+
return "Overpass sonucu boş veya geçersiz.\n"
|
| 728 |
+
|
| 729 |
+
elements = data.get("elements", [])
|
| 730 |
+
if not elements:
|
| 731 |
+
return "Overpass sonucu: hiç element bulunamadı.\n"
|
| 732 |
+
|
| 733 |
+
total_nodes = sum(1 for e in elements if e.get("type") == "node")
|
| 734 |
+
total_ways = sum(1 for e in elements if e.get("type") == "way")
|
| 735 |
+
total_rel = sum(1 for e in elements if e.get("type") == "relation")
|
| 736 |
+
|
| 737 |
+
# Basit tag istatistikleri
|
| 738 |
+
amenity_counts = {}
|
| 739 |
+
leisure_counts = {}
|
| 740 |
+
shop_counts = {}
|
| 741 |
+
highway_counts = {}
|
| 742 |
+
railway_counts = {}
|
| 743 |
+
pt_counts = {}
|
| 744 |
+
|
| 745 |
+
examples = []
|
| 746 |
+
|
| 747 |
+
for e in elements[:max_examples]:
|
| 748 |
+
etype = e.get("type")
|
| 749 |
+
tags = e.get("tags", {})
|
| 750 |
+
name = tags.get("name", "(isimsiz)")
|
| 751 |
+
|
| 752 |
+
amenity = tags.get("amenity")
|
| 753 |
+
leisure = tags.get("leisure")
|
| 754 |
+
shop = tags.get("shop")
|
| 755 |
+
highway = tags.get("highway")
|
| 756 |
+
railway = tags.get("railway")
|
| 757 |
+
pt = tags.get("public_transport")
|
| 758 |
+
opening_hours = tags.get("opening_hours")
|
| 759 |
+
wheelchair = tags.get("wheelchair")
|
| 760 |
+
|
| 761 |
+
if amenity:
|
| 762 |
+
amenity_counts[amenity] = amenity_counts.get(amenity, 0) + 1
|
| 763 |
+
if leisure:
|
| 764 |
+
leisure_counts[leisure] = leisure_counts.get(leisure, 0) + 1
|
| 765 |
+
if shop:
|
| 766 |
+
shop_counts[shop] = shop_counts.get(shop, 0) + 1
|
| 767 |
+
if highway:
|
| 768 |
+
highway_counts[highway] = highway_counts.get(highway, 0) + 1
|
| 769 |
+
if railway:
|
| 770 |
+
railway_counts[railway] = railway_counts.get(railway, 0) + 1
|
| 771 |
+
if pt:
|
| 772 |
+
pt_counts[pt] = pt_counts.get(pt, 0) + 1
|
| 773 |
+
|
| 774 |
+
# Örnek satır
|
| 775 |
+
tag_parts = []
|
| 776 |
+
for k in ["amenity", "leisure", "shop", "highway", "railway", "public_transport",
|
| 777 |
+
"opening_hours", "wheelchair"]:
|
| 778 |
+
v = tags.get(k)
|
| 779 |
+
if v:
|
| 780 |
+
tag_parts.append(f"{k}={v}")
|
| 781 |
+
|
| 782 |
+
tag_text = ", ".join(tag_parts) if tag_parts else "etiket yok"
|
| 783 |
+
examples.append(f"- {etype} | {name} | {tag_text}")
|
| 784 |
+
|
| 785 |
+
def dict_to_lines(title, d):
|
| 786 |
+
if not d:
|
| 787 |
+
return []
|
| 788 |
+
items = sorted(d.items(), key=lambda x: -x[1])
|
| 789 |
+
lines = [title]
|
| 790 |
+
for k, v in items:
|
| 791 |
+
lines.append(f" - {k}: {v}")
|
| 792 |
+
return lines
|
| 793 |
+
|
| 794 |
+
lines = [
|
| 795 |
+
f"Toplam node sayısı: {total_nodes}",
|
| 796 |
+
f"Toplam way sayısı: {total_ways}",
|
| 797 |
+
f"Toplam relation sayısı: {total_rel}",
|
| 798 |
+
"",
|
| 799 |
+
]
|
| 800 |
+
lines += dict_to_lines("Amenity türleri:", amenity_counts)
|
| 801 |
+
lines += dict_to_lines("Leisure türleri:", leisure_counts)
|
| 802 |
+
lines += dict_to_lines("Shop türleri:", shop_counts)
|
| 803 |
+
lines += dict_to_lines("Highway türleri:", highway_counts)
|
| 804 |
+
lines += dict_to_lines("Railway türleri:", railway_counts)
|
| 805 |
+
lines += dict_to_lines("Public transport türleri:", pt_counts)
|
| 806 |
+
|
| 807 |
+
if examples:
|
| 808 |
+
lines.append("")
|
| 809 |
+
lines.append(f"İlk {len(examples)} elementten bazı örnekler:")
|
| 810 |
+
lines.extend(examples)
|
| 811 |
+
|
| 812 |
+
return "\n".join(lines)
|
| 813 |
|
| 814 |
|
| 815 |
|
|
|
|
| 826 |
temperature,
|
| 827 |
top_p,
|
| 828 |
compare_context, # mahalle karşılaştırma bağlamı
|
| 829 |
+
spatial_context, # 👈 yeni: son Overpass sonuç özeti
|
| 830 |
):
|
| 831 |
|
| 832 |
|
|
|
|
| 886 |
"Kullanıcı bu mahalleler hakkında soru sorarsa bu bağlama göre cevap ver:\n"
|
| 887 |
f"{compare_context}"
|
| 888 |
)
|
| 889 |
+
|
| 890 |
+
if spatial_context:
|
| 891 |
+
full_system += (
|
| 892 |
+
"\n\nAyrıca kullanıcı tarafından en son çalıştırılan bir Overpass (spatial) sorgusunun"
|
| 893 |
+
" özet sonuçları var. Kullanıcı bu sorgudan gelen veriler hakkında soru sorarsa,"
|
| 894 |
+
" bu özet bağlamına dayanarak cevap ver:\n"
|
| 895 |
+
f"{spatial_context}"
|
| 896 |
+
)
|
| 897 |
|
| 898 |
messages = [{"role": "system", "content": full_system}]
|
| 899 |
messages.extend(history)
|
|
|
|
| 923 |
gr.Markdown("## Mahalle Karşılaştırmalı Chat Botu")
|
| 924 |
|
| 925 |
compare_state = gr.State("")
|
| 926 |
+
spatial_state = gr.State("") # 👈 yeni: son Overpass sonuç özeti
|
| 927 |
+
|
| 928 |
|
| 929 |
with gr.Row():
|
| 930 |
# SOL SÜTUN: CHAT
|
|
|
|
| 942 |
"Qwen/Qwen2.5-72B-Instruct", # 72B
|
| 943 |
|
| 944 |
# Çok büyük model
|
| 945 |
+
"openai/gpt-oss-120b", # 120Bdı
|
| 946 |
],
|
| 947 |
label="Model Seç (Bu listedeki modeller Hugging Face Inference API chat_completion ile uyumludur)",
|
| 948 |
value="abacusai/Dracarys-72B-Instruct"
|
|
|
|
| 990 |
temperature_slider,
|
| 991 |
top_p_slider,
|
| 992 |
compare_state, # >>> mahalle karşılaştırma bağlamı
|
| 993 |
+
spatial_state, # >>> son Overpass sonucu özeti
|
| 994 |
+
|
| 995 |
],
|
| 996 |
)
|
| 997 |
|
|
|
|
| 1079 |
run_overpass_btn.click(
|
| 1080 |
fn=run_overpass_to_map,
|
| 1081 |
inputs=[overpass_box],
|
| 1082 |
+
outputs=[map_html, spatial_state], # 👈 harita + LLM için özet
|
| 1083 |
)
|
| 1084 |
|
| 1085 |
|
| 1086 |
+
|
| 1087 |
compare_btn.click(
|
| 1088 |
fn=prepare_comparison,
|
| 1089 |
inputs=[city_in, district1_in, neigh1_in, district2_in, neigh2_in],
|