Quantum / app.py
Nonabzbssbbsbs's picture
Create app.py
12efb2a verified
# 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"""
<div style="text-align: center; padding: 10px; background-color: #4CAF50; color: white; border-radius: 10px;">
<h1 style="margin: 0;">⚛️ QUANTUM FINAL: Баян-Өлгий AI Кеңесшісі ⛰️</h1>
</div>
<div style="margin: 15px 0; padding: 10px; border: 2px solid {'#FF5733' if 'ҚАУІПСІЗДІК' in initial_warning else '#33FF57'}; border-radius: 5px; background-color: #f0f0f0;">
<h3 style="margin: 0; color: #333;">{initial_warning.split(':')[0]}</h3>
<p style="white-space: pre-wrap; margin: 5px 0 0 0; color: #555;">{initial_warning.split(':')[1] if len(initial_warning.split(':')) > 1 else initial_warning}</p>
</div>
"""
)
with gr.Tabs():
# --- 1. Ауа Райы & Карта ---
with gr.TabItem("🌤️ Ауа Райы, Талдау & Карта"):
gr.Markdown(f"### Баян-Өлгий үшін ең сенімді 7 күндік болжам")
# Толық деректер кестесі
gr.DataFrame(
value=initial_df,
headers=list(initial_df.columns),
row_count="dynamic",
interactive=False,
label="Ауа Райының Толық Деректері (Жел, Қар, Аяз)",
wrap=True,
type="pandas"
)
# Қазақша Болжам/Талдауды көрсету
gr.Markdown("### 🧠 Quantum Талдауы (Қазақша)")
gr.Markdown(initial_analysis)
gr.Markdown("### 🗺️ Баян-Өлгий Картасы")
gr.HTML(f"""
<iframe
width="100%" height="300" frameborder="0" scrolling="no" marginheight="0" marginwidth="0"
src="http://maps.google.com/maps?q=48.97,89.97&z=10&output=embed0{BAYAN_ULGII_LAT},{BAYAN_ULGII_LON}&z=10&output=embed">
</iframe>
""")
# --- 2. ML Қолданбалары (Мамандандырылған Болжамдар) ---
with gr.TabItem("🔬 ML Болжамдары (Өсімдік, Мал, Қоқыс)"):
gr.Markdown("### 🔬 Мамандандырылған Модельдермен Талдау (Қазақша)")
with gr.Row():
# Мал Ауруын Анықтау
with gr.Column():
gr.Markdown("#### 🐑 Мал Ауруын Анықтау (ShuffleNet V2)")
input_image_animal = gr.Image(type="pil", label="Мал суретін жүктеу")
output_text_animal = gr.Textbox(label="БОЛЖАМДЫ НӘТИЖЕ", interactive=False)
classify_btn_animal = gr.Button("Ауруды Анықтау")
classify_btn_animal.click(fn=lambda img: classify_image(img, task="animal"), inputs=input_image_animal, outputs=output_text_animal)
# Өсімдік Түрін/Ауруын Анықтау
with gr.Column():
gr.Markdown("#### 🌱 Өсімдік Түрін/Ауруын Анықтау (ShuffleNet V2)")
input_image_plant = gr.Image(type="pil", label="Өсімдік суретін жүктеу")
output_text_plant = gr.Textbox(label="БОЛЖАМДЫ НӘТИЖЕ", interactive=False)
classify_btn_plant = gr.Button("Түрін/Ауруын Анықтау")
classify_btn_plant.click(fn=lambda img: classify_image(img, task="plant"), inputs=input_image_plant, outputs=output_text_plant)
gr.Markdown("---")
# Қоқыс Түрін Анықтау
gr.Markdown("#### 🗑️ Қоқыс Түрін Анықтау (EfficientNet B0)")
with gr.Row():
input_image_trash = gr.Image(type="pil", label="Қоқыс суретін жүктеу")
output_text_trash = gr.Textbox(label="БОЛЖАМДЫ НӘТИЖЕ", interactive=False)
classify_btn_trash = gr.Button("Түрін Анықтау")
classify_btn_trash.click(fn=lambda img: classify_image(img, task="trash"), inputs=input_image_trash, outputs=output_text_trash)
# --- 3. Анықтамалық Сөздік ---
with gr.TabItem("📚 Анықтамалық Сөздік"):
gr.Markdown("### 📚 Ауылшаруашылық Терминдері")
gr.Markdown("""
* **Жайлау:** Жыл мезгіліне байланысты мал жайылатын жер.
* **Қыстақ:** Қысқы уақытта малды ұстайтын жылы жер.
* **Күйіс қайыру:** Малдың жеген шөбін қайта ауызға шығарып шайнауы.
""")
# Уақытты әр минут сайын жаңарту (Ауа райы емес, тек сағат)
demo.load(get_current_time, None, current_time_display, every=60)
demo.launch()