Nonabzbssbbsbs commited on
Commit
20ce41f
·
verified ·
1 Parent(s): 2ecb2d5

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +531 -0
app.py ADDED
@@ -0,0 +1,531 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import gradio as gr
4
+ import pandas as pd
5
+ import requests
6
+ import datetime
7
+ import time
8
+ import base64
9
+ import json
10
+ import logging
11
+ import tempfile
12
+ from typing import List, Tuple, Dict, Any
13
+
14
+ # Set logging level for debugging
15
+ logging.basicConfig(level=logging.INFO)
16
+
17
+ # -----------------------------------------------------------------
18
+ # 1. API CLIENT INITIALIZATION
19
+ # -----------------------------------------------------------------
20
+ GEMINI_CLIENT = None
21
+ API_STATUSES = {}
22
+
23
+ def initialize_api(name, env_key, client_class=None):
24
+ key = os.environ.get(env_key)
25
+ status = "❌"
26
+ client = None
27
+
28
+ if not key or "YOUR_" in key.upper() or len(key) < 10:
29
+ status = "⚠️ (Кілт Жоқ/Жарамсыз)"
30
+ API_STATUSES[name] = status
31
+ return None, status
32
+
33
+ try:
34
+ if client_class:
35
+ from google import genai
36
+ client = genai.Client(api_key=key)
37
+ status = "✅"
38
+ except Exception as e:
39
+ status = f"❌ (Қате: {e.__class__.__name__})"
40
+
41
+ API_STATUSES[name] = status
42
+ return client, status
43
+
44
+ # Gemini Initialization
45
+ try:
46
+ from google import genai
47
+ GEMINI_CLIENT, status = initialize_api('Gemini', 'GEMINI_API_KEY', genai.Client)
48
+ except Exception:
49
+ API_STATUSES['Gemini'] = "❌ (genai пакеті жоқ)"
50
+
51
+ # Non-client Keys
52
+ NEWS_API_KEY = os.environ.get('NEWS_API_KEY')
53
+ OPENWEATHER_API_KEY = os.environ.get('OPENWEATHER_API_KEY')
54
+ OPENAI_KEY = os.environ.get('OPENAI_API_KEY')
55
+ STABILITY_API_KEY = os.environ.get('STABILITY_API_KEY')
56
+
57
+ initialize_api('OpenAI Mod', 'OPENAI_API_KEY')
58
+ initialize_api('News', 'NEWS_API_KEY')
59
+ initialize_api('Weather', 'OPENWEATHER_API_KEY')
60
+ initialize_api('Stability (SDXL)', 'STABILITY_API_KEY')
61
+
62
+ API_STATUS_NOTE = " | ".join([f"{k} {v}" for k, v in API_STATUSES.items()])
63
+ print(f"[{datetime.datetime.now().strftime('%H:%M:%S')}] API Status: {API_STATUS_NOTE}")
64
+
65
+ # -----------------------------------------------------------------
66
+ # 2. CORE FUNCTIONS (V59.0 - Modern Chat Implementation)
67
+ # -----------------------------------------------------------------
68
+
69
+ # 2.1. Direct Gemini Text Chat (FIXED for 'messages' type)
70
+ def text_chat_gemini(message: str, chat_history: List[Dict[str, Any]]):
71
+ """
72
+ Handles the modern Gradio ChatInterface (list of dicts format).
73
+ e.g., history = [{"role": "user", "content": "..."}, {"role": "assistant", "content": "..."}]
74
+ """
75
+ if not message:
76
+ return ""
77
+
78
+ if GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅":
79
+ return "❌ Gemini API кілті орнатылмаған немесе жарамсыз. Қызметті Hugging Face Secrets-те тексеріңіз."
80
+
81
+ try:
82
+ # Convert Gradio 'messages' format to Gemini 'contents' format
83
+ contents = []
84
+ for entry in chat_history:
85
+ # Map Gradio 'assistant' role to Gemini 'model' role
86
+ role = "model" if entry["role"] == "assistant" else entry["role"]
87
+ contents.append({"role": role, "parts": [{"text": entry["content"]}]})
88
+
89
+ # Add the current user message
90
+ contents.append({"role": "user", "parts": [{"text": message}]})
91
+
92
+ system_instruction = "Сіз 'SQG Quantum Leap AI' атты интеллектуалды порталсыз. Жауаптарыңызды толығымен қазақ тілінде беріңіз. Достық, ақпараттық және кәсіби тонды сақтаңыз. Сіз Баян-Өлгий аймағына бағытталған ақпараттық орталықсыз."
93
+
94
+ response = GEMINI_CLIENT.models.generate_content(
95
+ model='gemini-2.5-flash',
96
+ contents=contents,
97
+ system_instruction=system_instruction
98
+ )
99
+ return response.text.strip()
100
+
101
+ except Exception as e:
102
+ return f"❌ Gemini Чат Қатесі: {e.__class__.__name__}. API кілтін тексеріңіз немесе лимит туралы ақпаратты қараңыз."
103
+
104
+
105
+ # 2.2. Weather Prediction
106
+ def get_weather_and_prediction():
107
+ lat, lon = 48.97, 89.97
108
+ output = "OpenWeatherMap Қатесі ❌."
109
+ prediction_output = "Gemini болжамы жоқ."
110
+
111
+ if not OPENWEATHER_API_KEY or API_STATUSES.get('Weather') != "✅":
112
+ return "OpenWeatherMap Key орнатылмаған немесе қате ❌", prediction_output
113
+
114
+ forecast_url = f"https://api.openweathermap.org/data/2.5/forecast?lat={lat}&lon={lon}&appid={OPENWEATHER_API_KEY}&units=metric&lang=kz"
115
+
116
+ try:
117
+ response = requests.get(forecast_url, timeout=5)
118
+ response.raise_for_status()
119
+ forecast_data = response.json()
120
+
121
+ current_data = forecast_data['list'][0]
122
+ temp = current_data['main']['temp']
123
+ wind_speed = current_data['wind']['speed']
124
+ desc = current_data['weather'][0]['description'].capitalize()
125
+
126
+ output = f"⛈️ Өлгий Ауа Райы (OpenWeatherMap)\n\n* Температура: **{temp} °C**\n* Жағдайы: **{desc}**\n* Жел: **{wind_speed} м/с**"
127
+
128
+ prediction_points = forecast_data['list'][1:4]
129
+
130
+ if GEMINI_CLIENT and API_STATUSES.get('Gemini') == "✅":
131
+ weather_text = json.dumps(prediction_points)
132
+ prompt = f"""
133
+ Сіз ауа райын талдаушысыз. Келесі JSON деректері Өлгий қаласының алдағы 9 сағаттағы ауа райы болжамдарын көрсетеді.
134
+ Толығымен қазақ тілінде, қарапайым сөздермен түсіндіріп беріңіз.
135
+ JSON деректері: {weather_text}
136
+ """
137
+
138
+ gemini_response = GEMINI_CLIENT.models.generate_content(
139
+ model='gemini-2.5-flash', contents=prompt
140
+ )
141
+ prediction_output = gemini_response.text.strip()
142
+
143
+ return output, prediction_output
144
+
145
+ except Exception as e:
146
+ return f"Белгісіз Қате: {e.__class__.__name__}", prediction_output
147
+
148
+ # 2.3. Image Generation (Stability AI SDXL-Turbo)
149
+ def generate_image_sdxl(prompt):
150
+ if not STABILITY_API_KEY or API_STATUSES.get('Stability (SDXL)') != "✅":
151
+ return None, "Stability API Key орнатылмаған немесе қате ❌"
152
+
153
+ if not prompt:
154
+ return None, "Мәтінді енгізіңіз."
155
+
156
+ url = "https://api.stability.ai/v2beta/stable-image/generate/sd3"
157
+
158
+ headers = { "authorization": f"Bearer {STABILITY_API_KEY}", "accept": "image/*" }
159
+ data = {
160
+ "prompt": f"Detailed cinematic photo, Kazakh culture theme, high resolution, soft lighting, 8k, {prompt}",
161
+ "output_format": "jpeg", "aspect_ratio": "1:1", "model": "sd3-medium"
162
+ }
163
+
164
+ try:
165
+ response = requests.post(url, headers=headers, files={'none': ''}, data=data, timeout=30)
166
+ response.raise_for_status()
167
+
168
+ if response.status_code == 200:
169
+ base64_img = base64.b64encode(response.content).decode("utf-8")
170
+ return f"data:image/jpeg;base64,{base64_img}", "Сурет сәтті жасалды ✅"
171
+ else:
172
+ return None, f"SDXL Қатесі: {response.status_code} - {response.text[:100]}"
173
+
174
+ except Exception as e:
175
+ return None, f"Сурет Генерациялау Қатесі: {e.__class__.__name__}"
176
+
177
+
178
+ # 2.4. AI Voice Chat (Gemini)
179
+ def process_voice_chat(audio_path):
180
+ if not audio_path or GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅":
181
+ return "Дауыс жазбасы жоқ", "Gemini API Қатесі ❌"
182
+
183
+ audio_file = None
184
+ try:
185
+ transcribe_prompt = "Transcribe the audio and provide ONLY the text in the original language. Do not add any extra commentary."
186
+
187
+ audio_file = GEMINI_CLIENT.upload_file(file=audio_path)
188
+
189
+ transcribe_response = GEMINI_CLIENT.models.generate_content(
190
+ model='gemini-2.5-flash', contents=[transcribe_prompt, audio_file]
191
+ )
192
+ original_text = transcribe_response.text.strip()
193
+
194
+ chat_prompt = f"Сіз 'SQG Quantum Leap AI'-сіз. Сізге келесі сұрақ қойылды. Жауабыңызды толығымен **қазақ тілінде** беріңіз:\n\nСұрақ: {original_text}"
195
+ chat_response = GEMINI_CLIENT.models.generate_content(
196
+ model='gemini-2.5-flash', contents=chat_prompt
197
+ )
198
+
199
+ GEMINI_CLIENT.delete_file(audio_file.name)
200
+
201
+ ai_response_text = chat_response.text.strip()
202
+
203
+ return original_text, ai_response_text
204
+
205
+ except Exception as e:
206
+ if audio_file:
207
+ try:
208
+ GEMINI_CLIENT.delete_file(audio_file.name)
209
+ except:
210
+ pass
211
+ return "Түпнұсқа мәтін қатесі", f"ЖИ Сөйлесу Қатесі: {e.__class__.__name__}. Gemini-ге аудио жіберу қатесі."
212
+
213
+
214
+ # 2.5. Vision (Image Analysis)
215
+ def analyze_vision_gemini(img):
216
+ if img is None or GEMINI_CLIENT is None or API_STATUSES.get('Gemini') != "✅":
217
+ df = pd.DataFrame({"Нәтиже": ["Қате"], "Сенімділік": ["-"]})
218
+ return df, "Gemini API Қатесі ❌"
219
+
220
+ vision_file = None
221
+ temp_img_path = None
222
+ try:
223
+ with tempfile.NamedTemporaryFile(suffix=".jpeg", delete=False) as tmp:
224
+ img.save(tmp.name, format="JPEG")
225
+ temp_img_path = tmp.name
226
+
227
+ vision_file = GEMINI_CLIENT.upload_file(file=temp_img_path)
228
+
229
+ prompt = "Analyze this image in detail and provide ONLY the analysis in fluent Kazakh. Start with a short, encouraging greeting."
230
+ response = GEMINI_CLIENT.models.generate_content(
231
+ model='gemini-2.5-flash', contents=[prompt, vision_file]
232
+ )
233
+
234
+ GEMINI_CLIENT.delete_file(vision_file.name)
235
+ os.unlink(temp_img_path)
236
+
237
+ full_text = response.text.strip()
238
+ df = pd.DataFrame([["Жасанды Интеллект Талдауы", "Жоғары"]], columns=["Нәтиже", "Сенімділік"])
239
+ return df, f"Талдау Ескертпесі: {full_text}"
240
+
241
+ except Exception as e:
242
+ if vision_file:
243
+ try: GEMINI_CLIENT.delete_file(vision_file.name)
244
+ except: pass
245
+ if temp_img_path and os.path.exists(temp_img_path):
246
+ os.unlink(temp_img_path)
247
+
248
+ df = pd.DataFrame({"Нәтиже": ["Қате"], "Сенімділік": ["-"]})
249
+ return df, f"Gemini Vision Қатесі: {e.__class__.__name__}"
250
+
251
+
252
+ # 2.6. News and Moderation
253
+ def get_latest_news(query):
254
+ if not NEWS_API_KEY or API_STATUSES.get('News') != "✅": return "NewsAPI Key орнатылмаған немесе қате ❌."
255
+
256
+ if not query: query = "Kazakhstan OR Mongolia OR Kazakh Diaspora"
257
+ url = f"https://newsapi.org/v2/everything?q={query}&language=en&sortBy=publishedAt&apiKey={NEWS_API_KEY}&pageSize=5"
258
+ try:
259
+ response = requests.get(url, timeout=10)
260
+ response.raise_for_status()
261
+ data = response.json()
262
+ articles = data.get('articles', [])
263
+
264
+ if not articles: return f"Табылған жаңалықтар жоқ: '{query}'"
265
+
266
+ article_summaries = "\n---\n".join([f"Атауы: {a.get('title')}. Қысқаша: {a.get('description') or 'N/A'}" for a in articles])
267
+
268
+ prompt = f"""
269
+ Төмендегі 5 жаңалықтың атаулары мен қысқаша сипаттамалары берілген.
270
+ Оларды 1-ден 5-ке дейін нөмірлеп, әрқайсысын 1 сөйлеммен толығымен қазақ тілінде түсіндіріп беріңіз.
271
+ Жауапты '🚨 Соңғы Жаңалықтар:' деген сөзбен бастаңыз.
272
+
273
+ Мәтін:
274
+ {article_summaries}
275
+ """
276
+
277
+ if GEMINI_CLIENT and API_STATUSES.get('Gemini') == "✅":
278
+ summary_response = GEMINI_CLIENT.models.generate_content(
279
+ model='gemini-2.5-flash', contents=prompt
280
+ )
281
+ return summary_response.text.strip()
282
+ else:
283
+ output = "🚨 Соңғы Жаңалықтар (Gemini қорытындысы жоқ. Ағылшын тіліндегі деректер):\n\n"
284
+ for i, article in enumerate(articles):
285
+ title = article.get('title', 'Атауы жоқ')
286
+ source = article.get('source', {}).get('name', 'Белгісіз')
287
+ output += f"{i+1}. **{title}**\n(Дереккөз: {source})\n\n"
288
+ return output.strip()
289
+
290
+ except Exception as e:
291
+ return f"Жаңалықтар Қатесі: {e.__class__.__name__}"
292
+
293
+ def add_post_with_moderation(current_state, new_message):
294
+ if not new_message: return current_state, "\n\n---\n\n".join(current_state), time.time(), "Модерация ✅"
295
+
296
+ is_toxic, ai_note = False, "Модерация ✅"
297
+ if OPENAI_KEY and API_STATUSES.get('OpenAI Mod') == "✅":
298
+ try:
299
+ mod_response = requests.post(
300
+ "https://api.openai.com/v1/moderations",
301
+ headers={"Authorization": f"Bearer {OPENAI_KEY}", "Content-Type": "application/json"},
302
+ json={"input": new_message}
303
+ )
304
+ mod_response.raise_for_status()
305
+ data = mod_response.json()
306
+ if data["results"][0]["flagged"]:
307
+ is_toxic = True
308
+ ai_note = "🛡️ Қабылданбады (Токсикалық Контент)"
309
+ except Exception:
310
+ ai_note = "Модерация Қатесі ⚠️"
311
+
312
+ if is_toxic:
313
+ return current_state, "\n\n---\n\n".join(current_state), time.time(), ai_note
314
+
315
+ now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8))).strftime('%H:%M')
316
+ formatted_msg = "[{}] Хабарлама: {}".format(now, new_message)
317
+ updated_state = [formatted_msg] + current_state
318
+
319
+ return updated_state[:10], "\n\n---\n\n".join(updated_state[:10]), time.time(), ai_note
320
+
321
+ def get_local_time_and_holiday(last_active):
322
+ now = datetime.datetime.now(datetime.timezone(datetime.timedelta(hours=8)))
323
+ time_str = now.strftime('%Y жылғы %B айының %d күні, сағат %H:%M')
324
+
325
+ holiday_note = ""
326
+ # Example holidays for Bayan-Olgii/Mongolia
327
+ if now.month == 7 and now.day in [11, 12, 13, 14, 15]:
328
+ holiday_note = "Бүгін - Наадам Мерекесі (Ұлттық Мереке) 🇲🇳"
329
+ elif now.month == 12 and now.day == 29:
330
+ holiday_note = "Бүгін - Тәуелсіздік Күні 🇲🇳"
331
+
332
+ return f"⏱️ Өлгий (Моңғолия) Уақыты:\n\n**{time_str}**\n\n{holiday_note}"
333
+
334
+
335
+ # -----------------------------------------------------------------
336
+ # 3. GRADIO INTERFACE (V59.0 - Starry Night Theme & Modern Chat)
337
+ # -----------------------------------------------------------------
338
+
339
+ # (V59.0) ҚАЙТАРУ: Сізге ұнаған 'Жұлдызды Түн' тақырыбы (Dark Mode)
340
+ # Бұл CSS 'style.css' файлын қажет етпейді, кодтың өзіне енгізілген.
341
+ css_style = """
342
+ /* V59.0: Vincent Van Gogh Starry Night Theme (Fixed) */
343
+ body {
344
+ 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;
345
+ background-size: cover !important;
346
+ background-attachment: fixed !important;
347
+ background-position: center !important;
348
+ color: #f0f0f0 !important;
349
+ }
350
+ .gradio-container {
351
+ background: rgba(0, 0, 0, 0.8) !important; /* Қараңғы фон (80%) */
352
+ border-radius: 20px !important;
353
+ padding: 20px !important;
354
+ color: #f0f0f0 !important;
355
+ box-shadow: 0 0 40px rgba(255, 215, 0, 0.5); /* Gold shadow for contrast */
356
+ }
357
+ h1, h3 { color: #ffd700 !important; font-family: sans-serif; }
358
+ /* Input and text boxes styling */
359
+ .gradio-box, .gr-box, .gr-form, .gr-input, .gr-textarea {
360
+ background: rgba(40, 40, 40, 0.9) !important;
361
+ color: #f0f0f0 !important;
362
+ border: 1px solid #1a4d95 !important;
363
+ border-radius: 8px !important;
364
+ }
365
+ /* Button styling (Gold/Navy contrast) */
366
+ .gr-button {
367
+ background: #ffd700 !important;
368
+ color: #1a4d95 !important;
369
+ font-weight: bold !important;
370
+ border-radius: 12px !important;
371
+ transition: all 0.2s;
372
+ }
373
+ .gr-button:hover {
374
+ background: #ffc400 !important;
375
+ transform: translateY(-2px);
376
+ box-shadow: 0 4px 10px rgba(255, 215, 0, 0.5);
377
+ }
378
+ /* Active Tab styling */
379
+ .gr-tab-button.selected {
380
+ background: #1a4d95 !important;
381
+ color: #ffd700 !important;
382
+ border-top-left-radius: 10px;
383
+ border-top-right-radius: 10px;
384
+ }
385
+ /* Chatbot styling (Dark mode) */
386
+ .gradio-chatbot {
387
+ border: 1px solid #ffd700 !important;
388
+ border-radius: 10px !important;
389
+ background-color: rgba(0, 0, 0, 0.5) !important;
390
+ padding: 10px;
391
+ }
392
+ /* Custom class for the status note */
393
+ .status-note {
394
+ font-size: 1.1em;
395
+ font-weight: bold;
396
+ padding: 10px;
397
+ border-radius: 10px;
398
+ background-color: rgba(255, 243, 205, 0.9); /* Ашық сары фон */
399
+ color: #856404; /* Қою сары мәтін */
400
+ text-align: center;
401
+ border: 1px solid #ffeeba;
402
+ }
403
+ """
404
+
405
+ with gr.Blocks(theme=gr.themes.Soft(), css=css_style, title="SQG Quantum Leap AI V59.0") as interface:
406
+ # State variables
407
+ message_state = gr.State([])
408
+ last_active = gr.State(0)
409
+
410
+ # Header
411
+ gr.Markdown(f"<h1><center>🌌 SQG Quantum Leap AI: Баян-Өлгий</center></h1>")
412
+ gr.Markdown(f"<div class='status-note'>Мультимодалды ЖИ-қызметтердің КҮЙІ: {API_STATUS_NOTE}</div>")
413
+ # Removed the clunky "Welcome" text
414
+
415
+ with gr.Tabs():
416
+
417
+ # 1. DEDICATED GEMINI TEXT CHAT (V59.0 - Modern 'messages' type)
418
+ with gr.TabItem("💬 Gemini Чат"):
419
+ gr.Markdown("## Gemini - Тікелей Сұрақ-Жауап (Қазақ тілінде)")
420
+ gr.Markdown("Сұрағыңызды енгізіңіз. Gemini-2.5 Flash моделі сізге қазақ тіліндегі ең жылдам және дәл жауаптарды ұсынады.")
421
+
422
+ # FIX: Added type='messages' to fix the UserWarning and ensure compatibility
423
+ gr.ChatInterface(
424
+ fn=text_chat_gemini,
425
+ chatbot=gr.Chatbot(height=550, type="messages"), # This is the critical fix
426
+ textbox=gr.Textbox(placeholder="Сұрағыңызды енгізіңіз...", container=False, scale=7),
427
+ title="Gemini-мен Сөйлесу",
428
+ )
429
+
430
+
431
+ # 2. VOICE CHAT (Дауыс арқылы енгізу)
432
+ with gr.TabItem("🎙️ AI Сөйлесу"):
433
+ gr.Markdown("## Gemini - Дауыстық Интеллект (STT & LLM)")
434
+ gr.Markdown("Микрофонға сөйлеңіз. ЖИ дауысыңызды мәтінге аударып, сұраққа жауап береді.")
435
+
436
+ audio_input = gr.Audio(sources=["microphone"], type="filepath", label="Сұрағыңызды айтыңыз (аудио жазба)", autoplay=False)
437
+ voice_btn = gr.Button("🗣️ Сөйлесуді Бастау")
438
+
439
+ with gr.Row():
440
+ user_text_output = gr.Textbox(label="Сіздің Сөзіңіз (Gemini Аудармасы)", lines=2, interactive=False)
441
+ ai_text_output = gr.Textbox(label="ЖИ Жауабы (Мәтін)", lines=4, interactive=False)
442
+
443
+ voice_btn.click(fn=process_voice_chat, inputs=[audio_input], outputs=[user_text_output, ai_text_output])
444
+
445
+
446
+ # 3. IMAGE GENERATION
447
+ with gr.TabItem("✨ Сурет Жасау"):
448
+ gr.Markdown("## Stability AI - Генеративті Кескін (SDXL-Turbo)")
449
+ gr.Markdown("Қазақ мәдениетіне немесе сіз қалаған тақырыпқа сәйкес сипаттама беріңіз, сонда ЖИ бірегей сурет жасайды.")
450
+ prompt_input = gr.Textbox(label="Сурет Идеясын Енгізіңіз (ағылшынша немесе қазақша)", lines=2, placeholder="Мысалы: 'Көшпенділер даладағы жылқыларды айдап барады, күн батуы'")
451
+ gen_btn = gr.Button("🖼️ Сурет Жасауды Бастау")
452
+ with gr.Row():
453
+ image_output = gr.Image(label="Генерацияланған Сурет", type="filepath", height=450)
454
+ status_output = gr.Textbox(label="Күйі", lines=2, interactive=False)
455
+ gen_btn.click(fn=generate_image_sdxl, inputs=[prompt_input], outputs=[image_output, status_output])
456
+
457
+ # 4. VISION (Image Analysis)
458
+ with gr.TabItem("🖼️ Сурет Талдау"):
459
+ gr.Markdown("## Gemini Vision - Кескінді Аналитикалық Талдау")
460
+ gr.Markdown("Кез келген суретті жүктеңіз. Gemini оның ішіндегі мазмұнды толығымен қазақ тілінде талдап береді.")
461
+ with gr.Row():
462
+ img_input = gr.Image(type="pil", label="Сурет Жүктеу немесе Түсіру", height=350)
463
+ with gr.Column():
464
+ output_table = gr.Dataframe(headers=["Нәтиже", "Сенімділік"], label="ЖИ Нәтижесі (Қазақша)", row_count=1, col_count=(2, 'fixed'))
465
+ qazaq_note_output = gr.Textbox(label="Талдау Ескертпесі (Толық Қазақша Сипаттама)", lines=6, interactive=False)
466
+ submit_btn = gr.Button("▶️ Талдауды Бастау")
467
+ submit_btn.click(fn=analyze_vision_gemini, inputs=[img_input], outputs=[output_table, qazaq_note_output])
468
+
469
+
470
+ # 5. WEATHER & PREDICTION (Fixed NameError)
471
+ with gr.TabItem("🗺️ Ауа Райы & Болжам"):
472
+ gr.Markdown("## OpenWeatherMap & Gemini - Өлгийдің Ауа Райы")
473
+
474
+ initial_weather, initial_prediction = get_weather_and_prediction()
475
+
476
+ with gr.Row():
477
+ with gr.Column(scale=1):
478
+ # 1. Define weather_output
479
+ weather_output = gr.Markdown(value=initial_weather)
480
+ gr.Markdown("### Уақыт")
481
+ # 2. Define time_output
482
+ time_output = gr.Markdown(get_local_time_and_holiday(0))
483
+ # 3. Define time_refresh_btn
484
+ time_refresh_btn = gr.Button("⏱️ Уақытты Жаңарту")
485
+ # 4. Define weather_refresh_btn
486
+ refresh_btn = gr.Button("🔄 Ауа Райын Жаңарту")
487
+
488
+ with gr.Column(scale=2):
489
+ gr.Markdown("### Gemini Болжамы (3-9 сағат)")
490
+ # 5. Define prediction_output
491
+ prediction_output = gr.Textbox(
492
+ value=initial_prediction,
493
+ label="Жақын 3-9 Сағатқа Арналған Болжам (Gemini Талдауы)",
494
+ lines=5,
495
+ interactive=False
496
+ )
497
+
498
+ gr.HTML(value='<iframe src="http://googleusercontent.com/maps/google.com/1" width="100%" height="300" style="border:0; border-radius: 10px;"></iframe>', label="Карта")
499
+
500
+ # 6. Attach click handlers *after* all components are defined
501
+ time_refresh_btn.click(fn=get_local_time_and_holiday, inputs=last_active, outputs=time_output)
502
+ refresh_btn.click(fn=get_weather_and_prediction, outputs=[weather_output, prediction_output])
503
+
504
+
505
+ # 6. NEWS
506
+ with gr.TabItem("📰 Жаңалықтар & Ақпарат"):
507
+ gr.Markdown("## NewsAPI & Gemini - Әлемдік Жаңалықтарға Шолу")
508
+ news_query = gr.Textbox(label="Тақырып бойынша іздеу", placeholder="Мысалы: 'Қазақ музыкасы' немесе 'Моңғолия экономикасы'", lines=1)
509
+ news_btn = gr.Button("🔎 Жаңалықтарды Көру & Қазақша Түсіндіру")
510
+ news_output = gr.Textbox(label="Gemini Талдаған Жаңалықтар Қорытындысы", lines=10, interactive=False)
511
+ news_btn.click(fn=get_latest_news, inputs=[news_query], outputs=news_output)
512
+
513
+
514
+ # 7. HUB (Moderation Chat)
515
+ with gr.TabItem("📢 Хабарламалар (AI Модерация)"):
516
+ gr.Markdown("## OpenAI - Қауіпсіз Коммуникация Хабы")
517
+ gr.Markdown("Хабарлама жіберіңіз. OpenAI модерациясы оны жарияламас бұрын токсикалық мазмұнға тексереді.")
518
+ moderation_status = gr.Markdown("🛡️ Модерация Күйі (OpenAI)", elem_id="mod_status")
519
+ message_display = gr.Markdown(value="Ешқандай хабарлама жоқ...", label="Соңғы 10 Хабарлама Тарихы")
520
+ with gr.Row():
521
+ message_input = gr.Textbox(label="Жаңа Хабарлама", placeholder="Хабарлама енгізіңіз...", lines=2)
522
+ send_button = gr.Button("Жіберу (AI Тексереді)")
523
+ send_button.click(
524
+ fn=add_post_with_moderation, inputs=[message_state, message_input], outputs=[message_state, message_display, last_active, moderation_status]
525
+ )
526
+
527
+ # -----------------------------------------------------------------
528
+ # 4. LAUNCH INTERFACE
529
+ # -----------------------------------------------------------------
530
+ if __name__ == "__main__":
531
+ interface.launch()