Spaces:
Runtime error
Runtime error
| import os | |
| import io | |
| import gradio as gr | |
| import pandas as pd | |
| import requests | |
| import datetime | |
| import time | |
| import base64 | |
| import json | |
| import logging | |
| import tempfile | |
| from typing import List, Dict, Any | |
| import sys | |
| # Set logging level | |
| logging.basicConfig(level=logging.INFO) | |
| # ----------------------------------------------------------------- | |
| # 0. OPEN SOURCE LLM SETUP (Llama 3 8B Reserve) | |
| # ----------------------------------------------------------------- | |
| LLM_AVAILABLE = False | |
| LLM_STATUS = "❌ Llama 3 (Сөндірулі)" | |
| LLM_MODEL = None | |
| LLM_TOKENIZER = None | |
| try: | |
| # Requires: torch, transformers, accelerate, bitsandbytes | |
| from transformers import AutoModelForCausalLM, AutoTokenizer | |
| import torch | |
| # Initialization check (This step can be slow and memory intensive) | |
| LLM_MODEL_NAME = "meta-llama/Meta-Llama-3-8B-Instruct" | |
| LLM_TOKENIZER = AutoTokenizer.from_pretrained(LLM_MODEL_NAME) | |
| # Load model using 8-bit quantization to save RAM (Crucial for 16GB RAM) | |
| LLM_MODEL = AutoModelForCausalLM.from_pretrained( | |
| LLM_MODEL_NAME, | |
| device_map="auto", | |
| torch_dtype=torch.bfloat16, | |
| load_in_8bit=True # Important for memory efficiency on CPU/low-VRAM GPU | |
| ) | |
| LLM_AVAILABLE = True | |
| LLM_STATUS = "✅ Llama 3 8B (Резерв)" | |
| except ImportError: | |
| LLM_STATUS = "❌ Llama 3 (Пакет жоқ)" | |
| except Exception as e: | |
| LLM_STATUS = f"❌ Llama 3 (Қате: {e.__class__.__name__})" | |
| # ----------------------------------------------------------------- | |
| # 1. API CLIENT INITIALIZATION (Standardized) | |
| # ----------------------------------------------------------------- | |
| GEMINI_CLIENT = None | |
| API_STATUSES = {'OpenLLM': LLM_STATUS} | |
| def initialize_api(name, env_key, client_class=None): | |
| key = os.environ.get(env_key) | |
| status = "❌" | |
| client = None | |
| # 1. Key Presence Check | |
| if not key or "YOUR_" in key.upper() or len(key) < 10: | |
| status = "⚠️ (Кілт Жоқ/Жарамсыз)" | |
| return None, status | |
| try: | |
| # 2. Client Initialization Check | |
| if client_class: | |
| from google import genai | |
| client = genai.Client(api_key=key) | |
| status = "✅" | |
| except Exception as e: | |
| status = f"❌ (Қате: {e.__class__.__name__})" | |
| return client, status | |
| # Initialize Gemini Client (Primary AI) | |
| try: | |
| from google import genai | |
| GEMINI_CLIENT, status = initialize_api('Gemini', 'GEMINI_API_KEY', genai.Client) | |
| API_STATUSES['Gemini'] = status | |
| except Exception: | |
| API_STATUSES['Gemini'] = "❌ (genai пакеті жоқ)" | |
| # Check and store status for other APIs | |
| _, API_STATUSES['OpenAI Mod'] = initialize_api('OpenAI Mod', 'OPENAI_API_KEY') | |
| _, API_STATUSES['News'] = initialize_api('News', 'NEWS_API_KEY') | |
| _, API_STATUSES['Weather'] = initialize_api('Weather', 'OPENWEATHER_API_KEY') | |
| _, API_STATUSES['Stability (SDXL)'] = initialize_api('Stability (SDXL)', 'STABILITY_API_KEY') | |
| NEWS_API_KEY = os.environ.get('NEWS_API_KEY') | |
| OPENWEATHER_API_KEY = os.environ.get('OPENWEATHER_API_KEY') | |
| OPENAI_KEY = os.environ.get('OPENAI_API_KEY') | |
| STABILITY_API_KEY = os.environ.get('STABILITY_API_KEY') | |
| API_STATUS_NOTE = " | ".join([f"{k} {v}" for k, v in API_STATUSES.items()]) | |
| print(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] API Status: {API_STATUS_NOTE}") | |
| LAST_AI_RESPONSE = "" | |
| # ----------------------------------------------------------------- | |
| # 2. CORE FUNCTIONS | |
| # ----------------------------------------------------------------- | |
| # 190-жолдағы қатенің шығуын болдырмау үшін 'global' бірінші тұр. | |
| def text_to_speech_html(text): | |
| global LAST_AI_RESPONSE # <--- МІНДЕТТІ ТҮРДЕ БІРІНШІ ОПЕРАТОР | |
| LAST_AI_RESPONSE = text | |
| return f"""<div style="color: #ffd700; font-weight: bold;">🗣️ Ауызша оқуға дайын. Түймені басыңыз.</div>""" | |
| def play_last_response(): | |
| global LAST_AI_RESPONSE # <--- МІНДЕТТІ ТҮРДЕ БІРІНШІ ОПЕРАТОР | |
| if not LAST_AI_RESPONSE: | |
| return f"""<div style="color: red; font-weight: bold;">❌ Оқылатын мәтін жоқ.</div>""" | |
| clean_text = LAST_AI_RESPONSE[:500].replace('"', "'").replace('\n', ' ') | |
| js_script = f""" | |
| <script> | |
| function speakText(text, lang) {{ | |
| if ('speechSynthesis' in window) {{ | |
| window.speechSynthesis.cancel(); | |
| var utterance = new SpeechSynthesisUtterance(text); | |
| utterance.lang = 'kk'; | |
| utterance.pitch = 1; | |
| utterance.rate = 1.05; | |
| setTimeout(() => {{ | |
| window.speechSynthesis.speak(utterance); | |
| }}, 100); | |
| }} | |
| }} | |
| speakText("{clean_text}", "kk"); | |
| </script> | |
| """ | |
| return f"""<div style="color: #00ff00; font-weight: bold;">🎧 Оқылуда...</div>{js_script}""" | |
| # 2.1. PRIMARY CHAT FUNCTION (Gemini OR Llama 3 Fallback) | |
| def text_chat_gemini_or_llama(message: str, chat_history: List[List[str]]): | |
| if not message: return "" | |
| # 1. --- Try Gemini (Primary) --- | |
| if GEMINI_CLIENT and API_STATUSES.get('Gemini') == "✅": | |
| try: | |
| contents = [] | |
| for user_msg, model_msg in chat_history: | |
| if user_msg: | |
| contents.append({"role": "user", "parts": [{"text": user_msg}]}) | |
| if model_msg: | |
| contents.append({"role": "model", "parts": [{"text": model_msg}]}) | |
| contents.append({"role": "user", "parts": [{"text": message}]}) | |
| system_instruction = "Сіз 'SQG Quantum Leap AI' атты интеллект. Жауапты тек қазақ тілінде, достық тонмен беріңіз. Сіз Баян-Өлгий аймағына бағытталған ақпарат орталығысыз." | |
| response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=contents, system_instruction=system_instruction | |
| ) | |
| ai_text = response.text.strip() | |
| global LAST_AI_RESPONSE | |
| LAST_AI_RESPONSE = ai_text | |
| return ai_text | |
| except Exception as e: | |
| logging.error(f"Gemini API Error: {e}") | |
| # Fall through to Llama 3 if Gemini fails | |
| pass | |
| # 2. --- Fallback to Llama 3 (Backup) --- | |
| if LLM_AVAILABLE: | |
| try: | |
| system_prompt = "Сіз 'SQG Quantum Leap AI' атты интеллект. Жауапты тек қазақ тілінде, достық тонмен беріңіз." | |
| messages = [{"role": "system", "content": system_prompt}] | |
| for user_msg, model_msg in chat_history: | |
| if user_msg: | |
| messages.append({"role": "user", "content": user_msg}) | |
| if model_msg: | |
| messages.append({"role": "assistant", "content": model_msg}) | |
| messages.append({"role": "user", "content": message}) | |
| prompt = LLM_TOKENIZER.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) | |
| inputs = LLM_TOKENIZER(prompt, return_tensors="pt").to(LLM_MODEL.device) | |
| outputs = LLM_MODEL.generate( | |
| **inputs, max_new_tokens=256, temperature=0.7, do_sample=True | |
| ) | |
| ai_text = LLM_TOKENIZER.decode(outputs[0][inputs['input_ids'].shape[1]:], skip_special_tokens=True).strip() | |
| global LAST_AI_RESPONSE | |
| LAST_AI_RESPONSE = ai_text | |
| return ai_text + "\n\n(🌐 Llama 3 8B арқылы жауап берілді - Резерв)" | |
| except Exception as e: | |
| logging.error(f"Llama 3 LLM Error: {e}") | |
| return f"❌ Gemini API Қатесі және Llama 3 Резерві де істен шықты: {e.__class__.__name__}. Ресурстарды тексеріңіз." | |
| # 3. --- Total Failure --- | |
| return "❌ API Қатесі. Gemini API кілтін тексеріңіз немесе Llama 3 резерві іске қосылмаған." | |
| # 2.2. Weather Prediction (Only uses Gemini for prediction, will show basic weather if Gemini fails) | |
| def get_weather_and_prediction(): | |
| lat, lon = 48.97, 89.97 | |
| output = "OpenWeatherMap Қатесі ❌." | |
| prediction_output = "Gemini болжамы жоқ. (LLM резерві бұл функцияға қолдау көрсетпейді)" | |
| if not OPENWEATHER_API_KEY or API_STATUSES.get('Weather') != "✅": | |
| return "OpenWeatherMap Key Қате ❌", prediction_output | |
| forecast_url = f"https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={OPENWEATHER_API_KEY}&units=metric&lang=kz" | |
| try: | |
| response = requests.get(forecast_url, timeout=5) | |
| response.raise_for_status() | |
| forecast_data = response.json() | |
| current_data = forecast_data['list'][0] | |
| temp = current_data['main']['temp'] | |
| wind_speed = current_data['wind']['speed'] | |
| desc = current_data['weather'][0]['description'].capitalize() | |
| output = f"⛈️ Өлгий (Ағымдағы)\n\n* Температура: **{temp} °C**\n* Жағдайы: **{desc}**\n* Жел: **{wind_speed} м/с**" | |
| prediction_points = [forecast_data['list'][i] for i in range(0, min(len(forecast_data['list']), 40), 8)] | |
| if GEMINI_CLIENT and API_STATUSES.get('Gemini') == "✅": | |
| weather_text = json.dumps(prediction_points) | |
| prompt = f"Сіз ауа райын талдаушысыз. Келесі JSON деректері Өлгий қаласының алдағы 5 күндегі ауа райы болжамдарын көрсетеді. Толығымен қазақ тілінде, қарапайым 5 күндік шолу жасап беріңіз. JSON деректері: {weather_text}" | |
| gemini_response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=prompt | |
| ) | |
| prediction_output = gemini_response.text.strip() | |
| return output, prediction_output | |
| except Exception as e: | |
| return f"Белгісіз Қате: {e.__class__.__name__}", prediction_output | |
| # 2.3. Image Generation (API Dependent - No LLM reserve for this) | |
| def generate_image_sdxl(prompt): | |
| if not STABILITY_API_KEY or API_STATUSES.get('Stability (SDXL)') != "✅": | |
| return None, "Stability Key Қате ❌. Немесе API-ға қолжетімділік жоқ." | |
| if not prompt: | |
| return None, "Мәтінді енгізіңіз." | |
| url = "https://api.stability.ai/v2beta/stable-image/generate/sd3" | |
| headers = { "authorization": f"Bearer {STABILITY_API_KEY}", "accept": "image/*" } | |
| data = { | |
| "prompt": f"Detailed cinematic photo, Kazakh culture theme, high resolution, soft lighting, 8k, {prompt}", | |
| "output_format": "jpeg", "aspect_ratio": "1:1", "model": "sd3-medium" | |
| } | |
| try: | |
| response = requests.post(url, headers=headers, files={'none': ''}, data=data, timeout=30) | |
| response.raise_for_status() | |
| if response.status_code == 200: | |
| base64_img = base64.b64encode(response.content).decode("utf-8") | |
| return f"data:image/jpeg;base64,{base64_img}", "Сурет сәтті жасалды ✅" | |
| else: | |
| return None, f"SDXL Қатесі: {response.status_code}. API лимит." | |
| except Exception as e: | |
| return None, f"Сурет Қатесі: {e.__class__.__name__}. API байланысын тексеріңіз." | |
| # 2.4. AI Voice Chat (API Dependent - Uses Gemini for both ASR and Chat) | |
| def process_voice_chat(audio_path): | |
| if not audio_path: return "Дауыс жазбасы жоқ", "Gemini API Қатесі ❌" | |
| if GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅": | |
| return "Дауыс жазбасы жоқ", "GemINI API Қатесі ❌" | |
| audio_file = None | |
| try: | |
| transcribe_prompt = "Transcribe the audio and provide ONLY the text in the original language. Do not add any extra commentary." | |
| audio_file = GEMINI_CLIENT.upload_file(file=audio_path) | |
| transcribe_response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=[transcribe_prompt, audio_file] | |
| ) | |
| original_text = transcribe_response.text.strip() | |
| chat_prompt = f"Сіз 'SQG Quantum Leap AI'-сіз. Жауабыңызды толығымен **қазақ тілінде** беріңіз:\n\nСұрақ: {original_text}" | |
| chat_response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=chat_prompt | |
| ) | |
| GEMINI_CLIENT.delete_file(audio_file.name) | |
| return original_text, chat_response.text.strip() | |
| except Exception as e: | |
| if audio_file: | |
| try: GEMINI_CLIENT.delete_file(audio_file.name) | |
| except: pass | |
| return "Түпнұсқа мәтін қатесі", f"ЖИ Сөйлесу Қатесі: {e.__class__.__name__}." | |
| # 2.5. Vision (Image Analysis - API Dependent) | |
| def analyze_vision_gemini(img): | |
| if img is None: | |
| df = pd.DataFrame({"Нәтиже": ["Сурет жоқ"], "Сенімділік": ["-"]}) | |
| return df, "Сурет жүктеңіз." | |
| if GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅": | |
| df = pd.DataFrame({"Нәтиже": ["Қате"], "Сенімділік": ["-"]}) | |
| return df, "Gemini API Қатесі ❌" | |
| vision_file = None | |
| temp_img_path = None | |
| try: | |
| with tempfile.NamedTemporaryFile(suffix=".jpeg", delete=False) as tmp: | |
| img.save(tmp.name, format="JPEG") | |
| temp_img_path = tmp.name | |
| vision_file = GEMINI_CLIENT.upload_file(file=temp_img_path) | |
| prompt = "Analyze this image in detail and provide ONLY the analysis in fluent Kazakh. Start with a short, encouraging greeting." | |
| response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=[prompt, vision_file] | |
| ) | |
| GEMINI_CLIENT.delete_file(vision_file.name) | |
| os.unlink(temp_img_path) | |
| full_text = response.text.strip() | |
| df = pd.DataFrame([["ЖИ Талдауы", "Жоғары"]], columns=["Нәтиже", "Сенімділік"]) | |
| return df, f"Талдау: {full_text}" | |
| except Exception as e: | |
| if vision_file: | |
| try: GEMINI_CLIENT.delete_file(vision_file.name) | |
| except: pass | |
| if temp_img_path and os.path.exists(temp_img_path): | |
| os.unlink(temp_img_path) | |
| df = pd.DataFrame({"Нәтиже": ["Қате"], "Сенімділік": ["-"]}) | |
| return df, f"Gemini Vision Қатесі: {e.__class__.__name__}" | |
| # 2.6. News and Moderation (Strong key check) | |
| def get_latest_news(query): | |
| if not NEWS_API_KEY or API_STATUSES.get('News') != "✅": | |
| return "NewsAPI Key Қате ❌. Жаңалықтар қолжетімсіз." | |
| if not query: query = "Kazakhstan OR Mongolia OR Kazakh Diaspora" | |
| url = f"https://newsapi.org/v2/everything?q={query}&language=en&sortBy=publishedAt&apiKey={NEWS_API_KEY}&pageSize=5" | |
| try: | |
| response = requests.get(url, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| articles = data.get('articles', []) | |
| if not articles: return f"Жаңалықтар жоқ: '{query}'" | |
| article_summaries = "\n---\n".join([f"Атауы: {a.get('title')}. Қысқаша: {a.get('description') or 'N/A'}" for a in articles]) | |
| prompt = f"Төмендегі 5 жаңалықты 1-ден 5-ке дейін нөмірлеп, әрқайсысын 1 сөйлеммен толығымен қазақ тілінде түсіндіріп беріңіз. Жауапты '🚨 Жаңалықтар Шолуы:' деп бастаңыз. Мәтін: {article_summaries}" | |
| if GEMINI_CLIENT and API_STATUSES.get('Gemini') == "✅": | |
| summary_response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=prompt | |
| ) | |
| return summary_response.text.strip() | |
| else: | |
| return "🚨 Жаңалықтар (Gemini жоқ): Қорытындылау мүмкін емес." | |
| except Exception as e: | |
| return f"Жаңалықтар Қатесі: {e.__class__.__name__}. Кілтті немесе лимиттерді тексеріңіз." | |
| def add_post_with_moderation(current_state, new_message): | |
| if not new_message: return current_state, "\n\n---\n\n".join(current_state), time.time(), "Модерация ✅" | |
| is_toxic, ai_note = False, "Модерация ✅ (OpenAI)" | |
| if OPENAI_KEY and API_STATUSES.get('OpenAI Mod') == "✅": | |
| try: | |
| mod_response = requests.post( | |
| "https://api.openai.com/v1/moderations", | |
| headers={"Authorization": f"Bearer {OPENAI_KEY}", "Content-Type": "application/json"}, | |
| json={"input": new_message} | |
| ) | |
| mod_response.raise_for_status() | |
| data = mod_response.json() | |
| if data["results"][0]["flagged"]: | |
| is_toxic = True | |
| ai_note = "🛡️ Қабылданбады (Токсикалық Контент)" | |
| except Exception: | |
| ai_note = "Модерация Қатесі ⚠️" | |
| if is_toxic: | |
| return current_state, "\n\n---\n\n".join(current_state), time.time(), ai_note | |
| now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))).strftime('%H:%M') | |
| formatted_msg = "[{}] Хабарлама: {}".format(now, new_message) | |
| updated_state = [formatted_msg] + current_state | |
| return updated_state[:10], "\n\n---\n\n".join(updated_state[:10]), time.time(), ai_note | |
| def get_local_time_and_holiday(last_active): | |
| now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))) | |
| time_str = now.strftime('%Y-%m-%d, %H:%M') | |
| holiday_note = "" | |
| if now.month == 7 and now.day in [11, 12, 13]: | |
| holiday_note = "Бүгін - Наадам Мерекесі 🇲🇳" | |
| return f"⏱️ Өлгий Уақыты: **{time_str}**\n\n{holiday_note}" | |
| def translate_text_gemini(text, source_lang, target_lang="Қазақ"): | |
| if not text: return "Мәтін енгізіңіз." | |
| if GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅": | |
| return "❌ Gemini API Қатесі." | |
| prompt = f"Сіз жоғары дәлдіктегі аудармашысыз. Түпнұсқа тіл '{source_lang}' тілінен '{target_lang}' тіліне аударыңыз. Тек аударма мәтінін ғана беріңіз. Мәтін: '{text}'" | |
| try: | |
| response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=prompt | |
| ) | |
| return response.text.strip() | |
| except Exception as e: | |
| return f"❌ Аударма Қатесі: {e.__class__.__name__}" | |
| def get_map_ai_analysis(): | |
| if GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅": | |
| return "❌ Gemini API Қатесі." | |
| prompt = "Баян-Өлгий аймағының географиялық ерекшеліктері, климаты және осы аймақтың қазақ халқы үшін маңыздылығы туралы 5 қысқа фактіні толығымен қазақ тілінде, таза тілмен сипаттаңыз. Жауапты '🌐 Гео-Талдау:' деп бастаңыз." | |
| try: | |
| response = GEMINI_CLIENT.models.generate_content( | |
| model='gemini-2.5-flash', contents=prompt | |
| ) | |
| return response.text.strip() | |
| except Exception as e: | |
| return f"❌ Карта Талдауы Қатесі: {e.__class__.__name__}" | |
| # ----------------------------------------------------------------- | |
| # 3. GRADIO INTERFACE (Finalized Design) | |
| # ----------------------------------------------------------------- | |
| # Finalized CSS for stability and readability | |
| css_style = """ | |
| body { | |
| background-image: url('https://upload.wikimedia.org/wikipedia/commons/thumb/e/ea/Van_Gogh_Starry_Night_-_Restored.jpg/2560px-Van_Gogh_Starry_Night_-_Restored.jpg') !important; | |
| background-size: cover !important; | |
| background-attachment: fixed !important; | |
| background-position: center !important; | |
| color: #f0f0f0 !important; | |
| } | |
| .gradio-container { | |
| background: rgba(0, 0, 0, 0.95) !important; | |
| border-radius: 15px !important; | |
| padding: 20px !important; | |
| box-shadow: 0 0 30px rgba(70, 130, 180, 0.5); | |
| } | |
| h1, h3 { color: #ffd700 !important; font-family: sans-serif; } | |
| .gr-box, .gr-input, .gr-textarea { | |
| background: rgba(30, 30, 30, 0.9) !important; | |
| color: #f0f0f0 !important; | |
| border: 1px solid #4682b4 !important; | |
| border-radius: 6px !important; | |
| } | |
| .gr-button { | |
| background: #4682b4 !important; | |
| color: #ffffff !important; | |
| font-weight: bold !important; | |
| border-radius: 8px !important; | |
| } | |
| .gr-tab-button.selected { | |
| background: #1a4d95 !important; | |
| color: #ffd700 !important; | |
| } | |
| .status-note { | |
| background-color: rgba(255, 243, 205, 0.9); | |
| color: #856404; | |
| text-align: center; | |
| padding: 5px; | |
| border-radius: 5px; | |
| } | |
| .gradio-chatbot { | |
| background-color: rgba(255, 255, 255, 0.05) !important; | |
| } | |
| """ | |
| with gr.Blocks(theme=gr.themes.Soft(), css=css_style, title="SQG Quantum Leap AI V69.0") as interface: | |
| # State variables | |
| message_state = gr.State([]) | |
| last_active = gr.State(0) | |
| # Header | |
| gr.Markdown(f"<h1><center>🌌 SQG Quantum Leap AI: Баян-Өлгий</center></h1>") | |
| gr.Markdown(f"<div class='status-note'>ЖИ Қызметтер Күйі: {API_STATUS_NOTE}</div>") | |
| with gr.Tabs(): | |
| # 1. DEDICATED HYBRID CHAT (Uses Gemini, falls back to Llama 3) | |
| with gr.TabItem("💬 Чат & 🔊"): | |
| gr.Markdown("## Гибридті ЖИ Чат (Gemini + Llama 3 Резерві)") | |
| tts_status_output = gr.HTML(value="Оқылатын мәтін жоқ.", visible=True) | |
| tts_btn = gr.Button("🔊 Соңғы Жауапты Оқыту (TTS)") | |
| chat_interface = gr.ChatInterface( | |
| fn=text_chat_gemini_or_llama, # <-- USING THE HYBRID FUNCTION | |
| textbox=gr.Textbox(placeholder="Сұрағыңызды енгізіңіз...", container=False), | |
| title="", | |
| submit_btn="Жіберу" | |
| ) | |
| tts_btn.click( | |
| fn=play_last_response, | |
| outputs=tts_status_output, | |
| queue=False | |
| ) | |
| # 2. VOICE CHAT | |
| with gr.TabItem("🎙️ Дауыс"): | |
| gr.Markdown("## Дауыстық Сөйлесу") | |
| audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Дауыс жазба") | |
| voice_btn = gr.Button("🗣️ Сөйлесуді Бастау") | |
| with gr.Row(): | |
| user_text_output = gr.Textbox(label="Сіздің Сөзіңіз", lines=2, interactive=False) | |
| ai_text_output = gr.Textbox(label="ЖИ Жауабы", lines=4, interactive=False) | |
| voice_btn.click(fn=process_voice_chat, inputs=[audio_input], outputs=[user_text_output, ai_text_output]) | |
| # 3. IMAGE GENERATION | |
| with gr.TabItem("✨ Сурет"): | |
| gr.Markdown("## Кескін Генерациясы") | |
| prompt_input = gr.Textbox(label="Сурет Идеясын Енгізіңіз", lines=2, placeholder="Сипаттама") | |
| gen_btn = gr.Button("🖼️ Сурет Жасау") | |
| with gr.Row(): | |
| image_output = gr.Image(label="Нәтиже", type="filepath", height=450) | |
| status_output = gr.Textbox(label="Күйі", lines=2, interactive=False) | |
| gen_btn.click(fn=generate_image_sdxl, inputs=[prompt_input], outputs=[image_output, status_output]) | |
| # 4. VISION (Image Analysis) | |
| with gr.TabItem("🖼️ Талдау"): | |
| gr.Markdown("## Кескінді Талдау") | |
| with gr.Row(): | |
| img_input = gr.Image(type="pil", label="Сурет Жүктеу", height=350) | |
| with gr.Column(): | |
| output_table = gr.Dataframe(headers=["Нәтиже", "Сенімділік"], label="ЖИ Нәтижесі", row_count=1, col_count=(2, 'fixed')) | |
| qazaq_note_output = gr.Textbox(label="Толық Талдау", lines=6, interactive=False) | |
| submit_btn = gr.Button("▶️ Талдауды Бастау") | |
| submit_btn.click(fn=analyze_vision_gemini, inputs=[img_input], outputs=[output_table, qazaq_note_output]) | |
| # 5. WEATHER & MAP AI | |
| with gr.TabItem("🗺️ Ауа Райы & Карта"): | |
| gr.Markdown("## Өлгий Ауа Райы & Гео-Талдау") | |
| initial_weather, initial_prediction = get_weather_and_prediction() | |
| initial_map_ai = get_map_ai_analysis() | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| weather_output = gr.Markdown(value=initial_weather) | |
| time_output = gr.Markdown(get_local_time_and_holiday(0)) | |
| refresh_btn = gr.Button("🔄 Жаңарту") | |
| time_refresh_btn = gr.Button("⏱️ Уақытты Жаңарту") | |
| with gr.Column(scale=2): | |
| gr.Markdown("### 5 Күндік Болжам") | |
| prediction_output = gr.Textbox(value=initial_prediction, label="Gemini Шолуы", lines=10, interactive=False) | |
| refresh_btn.click(fn=get_weather_and_prediction, outputs=[weather_output, prediction_output]) | |
| time_refresh_btn.click(fn=get_local_time_and_holiday, inputs=last_active, outputs=time_output) | |
| gr.Markdown("---") | |
| gr.Markdown("### 🌐 Карта & ЖИ Гео-Талдау") | |
| gr.HTML(value='<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1525.8675121175628!2d89.96783857500351!3d48.97116742514331!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x56a624597b6a67f1%3A0x6a053229b1d7d56e!2z0J7QvdC-0YDQsNC90Ysg0J7QvdC10YDQsA!5e0!3m2!1sru!2smn!4v1700000000000!5m2!1sru!2smn" width="100%" height="300" style="border:0; border-radius: 10px;" allowfullscreen="" loading="lazy"></iframe>', label="Карта") | |
| map_ai_output = gr.Textbox(value=initial_map_ai, label="Gemini Талдауы", lines=6, interactive=False) | |
| map_ai_btn = gr.Button("🧠 Гео-Талдауды Жаңарту") | |
| map_ai_btn.click(fn=get_map_ai_analysis, outputs=map_ai_output) | |
| # 6. NEWS | |
| with gr.TabItem("📰 Жаңалықтар"): | |
| gr.Markdown("## Жаңалықтар Шолуы") | |
| news_query = gr.Textbox(label="Тақырып бойынша іздеу", placeholder="Мысалы: 'Қазақ музыкасы'", lines=1) | |
| news_btn = gr.Button("🔎 Жаңалықтарды Көру") | |
| news_output = gr.Textbox(label="Gemini Қорытындысы", lines=10, interactive=False) | |
| news_btn.click(fn=get_latest_news, inputs=[news_query], outputs=news_output) | |
| # 7. HUB (Moderation Chat) | |
| with gr.TabItem("📢 Хабарламалар"): | |
| gr.Markdown("## Коммуникация Хабы") | |
| moderation_status = gr.Markdown("🛡️ Модерация Күйі", elem_id="mod_status") | |
| message_display = gr.Markdown(value="Хабарлама жоқ...", label="Соңғы 10 Хабарлама") | |
| with gr.Row(): | |
| message_input = gr.Textbox(label="Жаңа Хабарлама", placeholder="Хабарлама енгізіңіз...", lines=2) | |
| send_button = gr.Button("Жіберу (AI Тексереді)") | |
| send_button.click( | |
| fn=add_post_with_moderation, inputs=[message_state, message_input], outputs=[message_state, message_display, last_active, moderation_status] | |
| ) | |
| # 8. TRANSLATION TAB | |
| with gr.TabItem("🌍 Аударма"): | |
| gr.Markdown("## ЖИ Аудармашы") | |
| with gr.Row(): | |
| source_text = gr.Textbox(label="Түпнұсқа Мәтін", lines=5) | |
| source_lang_dropdown = gr.Dropdown( | |
| ["Орыс", "Түрік", "Моңғол", "Ағылшын"], | |
| label="Түпнұсқа Тіл", | |
| value="Орыс" | |
| ) | |
| translate_btn = gr.Button("➡️ Аударма") | |
| translated_text = gr.Textbox(label="Аударма", lines=5, interactive=False) | |
| translate_btn.click( | |
| fn=translate_text_gemini, | |
| inputs=[source_text, source_lang_dropdown], | |
| outputs=translated_text | |
| ) | |
| # ----------------------------------------------------------------- | |
| # 4. LAUNCH INTERFACE | |
| # ----------------------------------------------------------------- | |
| if __name__ == "__main__": | |
| interface.launch() |