# app.py (QUANTUM FINAL: Қарапайым, Әдемі & Нақты) import gradio as gr import requests import pandas as pd from openmeteo_requests import Client import openmeteo_requests from PIL import Image import torch import timm from torchvision import transforms from datetime import datetime import pytz import numpy as np # --- 0. Қазақша Классификация Сөздігі (Өсімдіктерге басымдықпен) --- # Бұл ImageNet-ке негізделген, бірақ қазақшаға бейімделген KZ_LABELS = { 0: "Ауылшаруашылық техникасы", 1: "Мал (Жылқы/Сиыр)", 2: "Ит / Қасқыр", 3: "Құс", 4: "Қоқыс (Пластик/Қағаз)", 5: "Шыны / Металл қалдықтары", 6: "Өсімдік Ауруы (Шіріген)", # Өсімдік ауруларына нақтырақ 7: "Өсімдік (Дені сау)", 10: "Көлік / Жүк машинасы", 12: "Қой/Ешкі", 16: "Дәнді дақылдар", 20: "Ағаш / Орман", 25: "Шөп / Жайылым", } # --- 1. Тұрақты Параметрлер & Геодеректер --- BAYAN_ULGII_LAT = 48.97 BAYAN_ULGII_LON = 89.97 DEVICE = "cpu" TIMEZONE = "Asia/Ulaanbaatar" # --- 2. Ауа Райы Кодтарының Қазақша Аудармасы --- def translate_weather_code(code): if code in [0]: return "Күн ашық ☀️" if code in [1, 2]: return "Аздаған бұлт 🌤️" if code in [3]: return "Бұлтты ☁️" if code in [45, 48]: return "Тұман 🌫️" if code in [51, 53, 55, 61, 63]: return "Аздаған жаңбыр 🌧️" if code in [65, 80, 81, 82]: return "Нөсер/Қатты жаңбыр ⛈️" if code in [56, 57, 66, 67, 71, 73]: return "Қар/Аязды жаңбыр 🌨️" if code in [75, 77, 85, 86]: return "Қалың қар ❄️" if code in [95, 96, 99]: return "Найзағай ⚡" return "Белгісіз" # --- 3. Модельдерді Жүктеу (Тұрақтылықты күшейту) --- TRASH_AVAILABLE = False ANIMAL_PLANT_AVAILABLE = False try: # Ең жеңіл ML моделі (Мал/Өсімдік) animal_plant_model = timm.create_model('shufflenet_v2_x0_5', pretrained=True).to(DEVICE).eval() # Жақсы дәлдікті ML моделі (Қоқыс) trash_model = timm.create_model('efficientnet_b0', pretrained=True).to(DEVICE).eval() transform_common = transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ]) ANIMAL_PLANT_AVAILABLE = True TRASH_AVAILABLE = True print("✅ Барлық жеңіл модельдер сәтті жүктелді.") except Exception as e: print(f"❌ Модельдерді жүктеу кезінде қате: {e}. ML функциялары іске қосылмайды.") # --- 4. Ауа Райы Логикасы --- def get_weather_data(): lat, lon = BAYAN_ULGII_LAT, BAYAN_ULGII_LON try: openmeteo = Client(requests) url = "https://api.open-meteo.com/v1/forecast" params = { "latitude": lat, "longitude": lon, "daily": ["weather_code", "temperature_2m_max", "temperature_2m_min", "precipitation_sum", "wind_speed_10m_max"], "timezone": "auto", "forecast_days": 7 } responses = openmeteo.weather_api(url, params=params) response = responses[0] daily = response.Daily() time_stamps = daily.Time() time_series = pd.to_datetime(time_stamps, unit="s").tz_localize(pytz.utc).tz_convert(TIMEZONE) # Деректерді алу және дөңгелектеу temp_max = daily.Variables(1).ValuesAsNumpy() temp_min = daily.Variables(2).ValuesAsNumpy() precip_sum = daily.Variables(3).ValuesAsNumpy() wind_speed = daily.Variables(4).ValuesAsNumpy() weather_code = daily.Variables(0).ValuesAsNumpy() daily_data = { "Күн": time_series.strftime('%d.%m'), "Сипаттама": [translate_weather_code(code) for code in weather_code], "Макс. Темп (°C)": temp_max.round(1), "Мин. Темп (°C)": temp_min.round(1), "Жауын-шашын (мм)": precip_sum.round(1), "Жел Жылдамдығы (км/сағ)": wind_speed.round(1) } df = pd.DataFrame(daily_data) # 4.1.1. ⚠️ Ерекше Экологиялық Ескертулер (Бас интерфейске шығатын) warnings = [] if np.any(wind_speed > 45): warnings.append("🚨 **ҚАТТЫ ЖЕЛ:** Жел 45 км/сағ-тан асады. Мал бағуға қауіпті.") if np.any(temp_min < -20): warnings.append("❄️ **ӨТЕ ҚАТТЫ АЯЗ:** -20°C төмен. Жылытуды күшейтіңіз.") if np.any(np.isin(weather_code, [75, 85, 86])): warnings.append("🌨️ **ЫҚТИМАЛ ҚАЛЫҢ ҚАР:** Қалың қар күтілуде. Жолдарға назар аударыңыз.") if np.any(precip_sum > 10): warnings.append("💧 **СУ ТАСҚЫНЫ ҚАУПІ:** Жауын-шашын күшті. Су басу қаупі бар.") warning_message = "✅ Қауіпсіздік ескертулері жоқ. Ауа райы тұрақты." if not warnings else "⚠️ **МАҢЫЗДЫ ҚАУІПСІЗДІК ЕСКЕРТУЛЕРІ:**\n- " + "\n- ".join(warnings) # 4.1.2. 🧠 Қазақша Болжам/Талдау analysis = [] if np.any(temp_max > 15): analysis.append("Алдағы күндері **күн жылы** болады.") if np.any(np.isin(weather_code, [0, 1])): analysis.append("Көп күндері **күн ашық** болады.") analysis_text = "✨ **Апталық Болжам Талдауы:**\n- " + ("\n- ".join(analysis) if analysis else "Жалпы алғанда ауа райы айтарлықтай өзгеріссіз.") return warning_message, df, analysis_text except Exception as e: return f"❌ Ауа райы деректерін алу қатесі: {e}", pd.DataFrame(), "Талдау қолжетімсіз." # 4.2. ML Жіктеу (Өзгеріссіз) def classify_image(image, task): if (task in ["animal", "plant"] and not ANIMAL_PLANT_AVAILABLE) or (task == "trash" and not TRASH_AVAILABLE): return "❌ Суретті жіктеу моделі іске қосылмады. Серверді қайта жүктеңіз немесе 'requirements' тексеріңіз." try: model, model_name = ( (trash_model, "EfficientNet B0 (5.3M)") if task == "trash" else (animal_plant_model, "ShuffleNet V2 (1.3M)") ) input_tensor = transform_common(image).unsqueeze(0).to(DEVICE) with torch.no_grad(): outputs = model(input_tensor) _, predicted = torch.max(outputs.data, 1) predicted_index = predicted.item() predicted_kz_label = KZ_LABELS.get(predicted_index, f"Белгісіз Код #{predicted_index}") if task == "trash": type_kz = "Қоқыс түрі" elif task == "animal": type_kz = "Мал Ауруы" else: type_kz = "Өсімдік Түрі / Ауруы" kz_response = f"**{type_kz}** болжамды нәтиже:\nБолжам: **{predicted_kz_label}**.\n\n" kz_response += f"✅ **Қолданылған Жеңіл Модель:** {model_name}.\n" kz_response += "❗ **Ескерту:** Бұл модельдер жалпы деректерде оқытылған. Дәл диагноз үшін **жергілікті маманға** жүгініңіз." return kz_response except Exception as e: return f"❌ Суретті жіктеу қатесі: {e}" # 4.3. Уақытты жаңарту (Әр минут сайын) def get_current_time(): try: tz = pytz.timezone(TIMEZONE) now = datetime.now(tz) return now.strftime("⌚ %H:%M:%S (%d.%m.%Y)") except Exception: return "⌚ Уақыт дерегі қолжетімсіз" # Қосымша іске қосылғанда деректерді алдын ала жүктеу initial_warning, initial_df, initial_analysis = get_weather_data() # --- 5. Ғажап Интерфейс (Gradio) --- # Әдемі, қарапайым және түсінікті тақырыпты таңдаймыз with gr.Blocks(title="Quantum FINAL: Баян-Өлгий AI", theme=gr.themes.Soft()) as demo: current_time_display = gr.Textbox(label=f"Баян-Өлгий Уақыты", value=get_current_time(), interactive=False, container=False) # 5.1. Басты HTML блок (Қарапайым және таза дизайн) header_html = gr.HTML( f"""
{initial_warning.split(':')[1] if len(initial_warning.split(':')) > 1 else initial_warning}