Mer1Alii commited on
Commit
2d4c3e5
·
verified ·
1 Parent(s): af5afb9

Apply user custom UI

Browse files
Files changed (1) hide show
  1. app.py +267 -51
app.py CHANGED
@@ -121,10 +121,10 @@ def generate_step(messages):
121
  """
122
  text = tokenizer.apply_chat_template(messages, tools=tools, tokenize=False, add_generation_prompt=True)
123
  inputs = tokenizer(text, return_tensors="pt").to(model.device)
124
-
125
  outputs = model.generate(**inputs, max_new_tokens=1024, temperature=0.3)
126
  response_text = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=False)
127
-
128
  # Qwen2.5 tool call formatında bitiş token'larını temizleme
129
  response_text = response_text.replace("<|im_end|>", "")
130
  return response_text
@@ -146,6 +146,34 @@ def parse_tool_calls(text):
146
  print(f"Tool parse hatası: {e} - Veri: {match}")
147
  return calls
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  def chat_interface(user_input, history):
150
  if not model:
151
  yield "Model yüklenemediği için yanıt verilemiyor."
@@ -155,16 +183,16 @@ def chat_interface(user_input, history):
155
  messages = [
156
  {"role": "system", "content": "Sen yetenekli bir afet takip asistanısın. Kullanıcı sorularına cevap verirken gerektiğinde 'get_earthquakes' ve 'get_wildfires' araçlarını kullan. Araçların sonuçlarını inceleyerek doğal dilde cevap ver. Bugünkü tarih: " + datetime.now().strftime("%Y-%m-%d")}
157
  ]
158
-
159
  for user_msg, asst_msg in history:
160
  messages.append({"role": "user", "content": user_msg})
161
  messages.append({"role": "assistant", "content": asst_msg})
162
-
163
  messages.append({"role": "user", "content": user_input})
164
-
165
  turn = 1
166
  final_output = ""
167
-
168
  # Maksimum 5 tool-calling döngüsü (Agentic Loop)
169
  for _ in range(5):
170
  try:
@@ -172,35 +200,37 @@ def chat_interface(user_input, history):
172
  response_text = generate_step(messages)
173
  messages.append({"role": "assistant", "content": response_text})
174
  except Exception as e:
175
- final_output += f"\n[Hata] Model çalıştırılamadı: {str(e)}"
176
  yield final_output
177
  break
178
-
179
  tool_calls = parse_tool_calls(response_text)
180
-
 
 
181
  # Eğer tool çağrısı yoksa, model nihai cevabı üretmiştir. Döngüden çık.
182
  if not tool_calls:
183
- # Sadece doğal dildeki cevabı ekle (varsa tool tagleri dışında kalan kısım)
184
- clean_response = re.sub(r"<tool_call>.*?</tool_call>", "", response_text, flags=re.DOTALL).strip()
185
- if clean_response:
186
- final_output += f"\n\n[Nihai Yanıt]:\n{clean_response}"
187
  yield final_output
188
  break
189
-
190
- # Tool çağrısı varsa UI'da göstermek için metin formatla
191
- turn_str = ""
192
-
 
193
  for call in tool_calls:
194
  func_name = call.get("name")
195
  args = call.get("arguments", {})
196
  args_str = ", ".join(f"{k}={v}" for k, v in args.items())
197
-
198
  # Aracı çalıştır
199
  if func_name in available_functions:
200
  try:
201
  result = available_functions[func_name](**args)
202
  res_json = json.dumps(result, ensure_ascii=False)
203
- turn_str += f"<div class='tool-box'><div class='tool-title'>🛠️ Araç: {func_name}</div><div class='tool-code'>Girdi: {args_str}</div><div class='tool-code'>Çıktı: {res_json[:200]}...</div></div>"
 
204
  # Sonucu modele geri besle
205
  messages.append({
206
  "role": "tool",
@@ -209,7 +239,7 @@ def chat_interface(user_input, history):
209
  })
210
  except Exception as e:
211
  error_msg = {"error": str(e)}
212
- turn_str += f"<div class='tool-box'><div class='tool-title'>⚠️ Hata: {func_name}</div><div class='tool-code'>{str(e)}</div></div>"
213
  messages.append({
214
  "role": "tool",
215
  "name": func_name,
@@ -217,60 +247,246 @@ def chat_interface(user_input, history):
217
  })
218
  else:
219
  error_msg = {"error": f"Bilinmeyen fonksiyon: {func_name}"}
220
- turn_str += f"<div class='tool-box'><div class='tool-title'>⚠️ Bilinmeyen Araç: {func_name}</div></div>"
221
  messages.append({
222
  "role": "tool",
223
  "name": func_name,
224
  "content": json.dumps(error_msg, ensure_ascii=False)
225
  })
226
-
227
- final_output += turn_str
228
  turn += 1
229
-
230
  # Ara adımları UI'da akarak göster (stream)
231
- yield final_output + "<br><i style='color:#666; font-size: 0.9em;'>💭 Model aksiyon alıyor...</i>"
232
 
233
  # ==========================================
234
- # 4. Gradio UI
235
  # ==========================================
236
  css = """
237
- body { background-color: #000000 !important; color: #e0e0e0; font-family: 'Inter', sans-serif; }
238
- .gradio-container { background: #000000 !important; border: none !important; }
239
- #chatbot { background: #000000 !important; border: none !important; box-shadow: none !important; }
240
- .message { border-radius: 12px !important; border: 1px solid #333 !important; padding: 14px !important; }
241
- .bot { background: #0a0a0a !important; color: #ccc !important; }
242
- .user { background: #1a1a1a !important; color: #fff !important; }
243
- .tool-box { background: #111; border: 1px solid #222; border-left: 3px solid #555; padding: 10px; margin: 8px 0; border-radius: 4px 8px 8px 4px; font-size: 0.85em; color: #999; }
244
- .tool-title { font-weight: 600; color: #bbb; margin-bottom: 4px; }
245
- .tool-code { font-family: monospace; background: #000; padding: 4px; border-radius: 4px; overflow-wrap: break-word; }
246
- .bubble-btn { background: #111 !important; border: 1px solid #333 !important; border-radius: 20px !important; color: #aaa !important; font-size: 0.85em !important; padding: 4px 12px !important; box-shadow: none !important; cursor: pointer; transition: 0.2s; min-width: auto !important; flex-grow: 0 !important; }
247
- .bubble-btn:hover { background: #222 !important; color: #fff !important; border-color: #555 !important; }
248
- #msg_box textarea { background: #111 !important; border: 1px solid #333 !important; color: white !important; border-radius: 12px !important; }
249
- #submit_btn { background: #222 !important; color: white !important; border: 1px solid #444 !important; border-radius: 12px !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  """
251
 
252
  with gr.Blocks(theme=gr.themes.Base(), css=css) as demo:
253
- gr.Markdown("<h1 style='text-align: center; color: #fff; font-weight: 300;'>🌍 Agentic Disaster Tracker</h1>")
254
-
255
- chatbot = gr.Chatbot(elem_id="chatbot", height=500, label="Asistan", show_label=False)
256
-
257
- with gr.Row():
258
- ex1 = gr.Button("Son depremler", elem_classes="bubble-btn")
259
- ex2 = gr.Button("Aktif yangınlar", elem_classes="bubble-btn")
260
- ex3 = gr.Button("Deprem ve yangınları birleştir", elem_classes="bubble-btn")
 
 
 
 
 
261
 
262
  with gr.Row():
263
  msg = gr.Textbox(placeholder="Afetlerle ilgili ne öğrenmek istersiniz?", label="Mesajınız", lines=1, show_label=False, elem_id="msg_box", scale=4)
264
  submit_btn = gr.Button("Gönder", variant="primary", scale=1, elem_id="submit_btn")
265
-
266
  ex1.click(lambda: "2026-07-25 ile 2026-07-30 tarihleri arasındaki 5.5 üzeri depremleri listele.", outputs=msg)
267
  ex2.click(lambda: "Şu anki aktif büyük orman yangınları hangileri? 3 tanesini getir.", outputs=msg)
268
  ex3.click(lambda: "Son 7 günde (2026-07-23 ile 2026-07-30) 6.0'dan büyük deprem oldu mu? Ayrıca şu an aktif orman yangını var mı?", outputs=msg)
269
-
270
  def respond(user_message, chat_history):
271
  # Arayüze kullanıcının mesajını ekle
272
  chat_history.append((user_message, ""))
273
-
274
  # Jeneratörden gelen kısımları adım adım güncelle
275
  for bot_message in chat_interface(user_message, chat_history[:-1]):
276
  chat_history[-1] = (user_message, bot_message)
@@ -280,4 +496,4 @@ with gr.Blocks(theme=gr.themes.Base(), css=css) as demo:
280
  msg.submit(respond, [msg, chatbot], [chatbot, msg], api_name=False)
281
 
282
  if __name__ == "__main__":
283
- demo.launch()
 
121
  """
122
  text = tokenizer.apply_chat_template(messages, tools=tools, tokenize=False, add_generation_prompt=True)
123
  inputs = tokenizer(text, return_tensors="pt").to(model.device)
124
+
125
  outputs = model.generate(**inputs, max_new_tokens=1024, temperature=0.3)
126
  response_text = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=False)
127
+
128
  # Qwen2.5 tool call formatında bitiş token'larını temizleme
129
  response_text = response_text.replace("<|im_end|>", "")
130
  return response_text
 
146
  print(f"Tool parse hatası: {e} - Veri: {match}")
147
  return calls
148
 
149
+ def _escape(text: str) -> str:
150
+ return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
151
+
152
+ def render_thinking(text: str) -> str:
153
+ """Modelin araç çağrısı öncesi/yanındaki serbest metnini ayrı bir 'düşünce' bloğu olarak gösterir."""
154
+ return (
155
+ f'<div class="think-block">'
156
+ f'<span class="think-label">düşünce</span>'
157
+ f'<div class="think-text">{_escape(text)}</div>'
158
+ f'</div>'
159
+ )
160
+
161
+ def render_tool(name: str, args_str: str, output_str: str, is_error: bool = False) -> str:
162
+ """Bir araç çağrısını girdi/çıktısıyla birlikte ayrı bir 'araç' bloğu olarak gösterir."""
163
+ cls = "tool-block tool-error" if is_error else "tool-block"
164
+ mark = "⚠" if is_error else ""
165
+ return (
166
+ f'<div class="{cls}">'
167
+ f'<span class="tool-label">araç çağrısı</span>'
168
+ f'<div class="tool-head"><span class="tool-dot"></span>{_escape(str(name))}{(" " + mark) if mark else ""}</div>'
169
+ f'<div class="tool-io"><span class="io-label">girdi</span>{_escape(args_str)}</div>'
170
+ f'<div class="tool-io"><span class="io-label">çıktı</span>{_escape(output_str)}</div>'
171
+ f'</div>'
172
+ )
173
+
174
+ def render_status(text: str = "model çalışıyor") -> str:
175
+ return f'<div class="status-line"><span class="pulse-dot"></span>{_escape(text)}</div>'
176
+
177
  def chat_interface(user_input, history):
178
  if not model:
179
  yield "Model yüklenemediği için yanıt verilemiyor."
 
183
  messages = [
184
  {"role": "system", "content": "Sen yetenekli bir afet takip asistanısın. Kullanıcı sorularına cevap verirken gerektiğinde 'get_earthquakes' ve 'get_wildfires' araçlarını kullan. Araçların sonuçlarını inceleyerek doğal dilde cevap ver. Bugünkü tarih: " + datetime.now().strftime("%Y-%m-%d")}
185
  ]
186
+
187
  for user_msg, asst_msg in history:
188
  messages.append({"role": "user", "content": user_msg})
189
  messages.append({"role": "assistant", "content": asst_msg})
190
+
191
  messages.append({"role": "user", "content": user_input})
192
+
193
  turn = 1
194
  final_output = ""
195
+
196
  # Maksimum 5 tool-calling döngüsü (Agentic Loop)
197
  for _ in range(5):
198
  try:
 
200
  response_text = generate_step(messages)
201
  messages.append({"role": "assistant", "content": response_text})
202
  except Exception as e:
203
+ final_output += render_tool("model", "", str(e), is_error=True)
204
  yield final_output
205
  break
206
+
207
  tool_calls = parse_tool_calls(response_text)
208
+ # <tool_call> etiketleri dışında kalan serbest metin: düşünce ya da nihai cevap
209
+ reasoning_text = re.sub(r"<tool_call>.*?</tool_call>", "", response_text, flags=re.DOTALL).strip()
210
+
211
  # Eğer tool çağrısı yoksa, model nihai cevabı üretmiştir. Döngüden çık.
212
  if not tool_calls:
213
+ if reasoning_text:
214
+ final_output += f"\n\n{reasoning_text}"
 
 
215
  yield final_output
216
  break
217
+
218
+ # Tool çağrısından önceki/yanındaki serbest metin varsa ayrı "düşünce" bloğu olarak göster
219
+ if reasoning_text:
220
+ final_output += render_thinking(reasoning_text)
221
+
222
  for call in tool_calls:
223
  func_name = call.get("name")
224
  args = call.get("arguments", {})
225
  args_str = ", ".join(f"{k}={v}" for k, v in args.items())
226
+
227
  # Aracı çalıştır
228
  if func_name in available_functions:
229
  try:
230
  result = available_functions[func_name](**args)
231
  res_json = json.dumps(result, ensure_ascii=False)
232
+ out_display = res_json[:200] + ("…" if len(res_json) > 200 else "")
233
+ final_output += render_tool(func_name, args_str, out_display)
234
  # Sonucu modele geri besle
235
  messages.append({
236
  "role": "tool",
 
239
  })
240
  except Exception as e:
241
  error_msg = {"error": str(e)}
242
+ final_output += render_tool(func_name, args_str, str(e), is_error=True)
243
  messages.append({
244
  "role": "tool",
245
  "name": func_name,
 
247
  })
248
  else:
249
  error_msg = {"error": f"Bilinmeyen fonksiyon: {func_name}"}
250
+ final_output += render_tool(func_name, args_str, "bilinmeyen araç", is_error=True)
251
  messages.append({
252
  "role": "tool",
253
  "name": func_name,
254
  "content": json.dumps(error_msg, ensure_ascii=False)
255
  })
256
+
 
257
  turn += 1
258
+
259
  # Ara adımları UI'da akarak göster (stream)
260
+ yield final_output + render_status("model aksiyon alıyor")
261
 
262
  # ==========================================
263
+ # 4. Gradio UI — düz (flat), AMOLED siyah + gri arayüz
264
  # ==========================================
265
  css = """
266
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&display=swap');
267
+
268
+ :root {
269
+ --bg: #000000;
270
+ --fg: #ededed;
271
+ --fg-dim: #9a9a9a;
272
+ --fg-dimmer: #5c5c5c;
273
+ --line: #232323;
274
+ --think: #8f8f8f;
275
+ }
276
+
277
+ * { box-sizing: border-box; }
278
+
279
+ body, .gradio-container {
280
+ background: var(--bg) !important;
281
+ color: var(--fg) !important;
282
+ font-family: 'Inter', system-ui, -apple-system, sans-serif !important;
283
+ }
284
+
285
+ .gradio-container {
286
+ border: none !important;
287
+ box-shadow: none !important;
288
+ max-width: 900px !important;
289
+ margin: 0 auto !important;
290
+ }
291
+
292
+ footer { display: none !important; }
293
+ ::selection { background: #3a3a3a; color: #fff; }
294
+
295
+ /* ince, gri kaydırma çubuğu */
296
+ ::-webkit-scrollbar { width: 6px; height: 6px; }
297
+ ::-webkit-scrollbar-thumb { background: #2a2a2a; border-radius: 4px; }
298
+ ::-webkit-scrollbar-track { background: transparent; }
299
+
300
+ /* ---------- başlık ---------- */
301
+ .header-wrap { text-align: center; padding: 30px 0 18px 0; }
302
+ .header-title { font-size: 1.35em; font-weight: 300; letter-spacing: 0.09em; color: #f2f2f2; }
303
+ .header-sub { font-size: 0.72em; letter-spacing: 0.22em; text-transform: uppercase; color: var(--fg-dimmer); margin-top: 6px; }
304
+
305
+ /* ---------- sohbet penceresi: tamamen düz, kutu yok ---------- */
306
+ #chatbot {
307
+ background: var(--bg) !important;
308
+ border: none !important;
309
+ box-shadow: none !important;
310
+ }
311
+ #chatbot .message-wrap,
312
+ #chatbot .wrap,
313
+ #chatbot .bot-row,
314
+ #chatbot .user-row {
315
+ background: transparent !important;
316
+ }
317
+ #chatbot .message {
318
+ background: transparent !important;
319
+ border: none !important;
320
+ box-shadow: none !important;
321
+ padding: 10px 6px !important;
322
+ font-size: 0.97em;
323
+ line-height: 1.65;
324
+ }
325
+ #chatbot .user {
326
+ color: #ffffff !important;
327
+ font-weight: 500;
328
+ }
329
+ #chatbot .bot {
330
+ color: var(--fg) !important;
331
+ }
332
+ /* mesajlar arası kutu değil, ince ayraç */
333
+ #chatbot .message-row:not(:first-child) {
334
+ border-top: 1px solid var(--line);
335
+ margin-top: 4px;
336
+ padding-top: 4px;
337
+ }
338
+
339
+ /* ---------- düşünce bloğu ---------- */
340
+ .think-block {
341
+ border-left: 1px dashed #444;
342
+ padding: 3px 0 3px 16px;
343
+ margin: 12px 0;
344
+ }
345
+ .think-label,
346
+ .tool-label {
347
+ display: block;
348
+ font-family: 'JetBrains Mono', monospace;
349
+ font-size: 0.65em;
350
+ letter-spacing: 0.14em;
351
+ text-transform: uppercase;
352
+ color: var(--fg-dimmer);
353
+ margin-bottom: 5px;
354
+ }
355
+ .think-text {
356
+ font-style: italic;
357
+ color: var(--think);
358
+ font-size: 0.92em;
359
+ line-height: 1.55;
360
+ white-space: pre-wrap;
361
+ }
362
+
363
+ /* ---------- araç bloğu ---------- */
364
+ .tool-block {
365
+ border-left: 1px solid #3a3a3a;
366
+ padding: 3px 0 8px 16px;
367
+ margin: 12px 0;
368
+ }
369
+ .tool-head {
370
+ font-family: 'JetBrains Mono', monospace;
371
+ font-size: 0.8em;
372
+ color: #c2c2c2;
373
+ display: flex;
374
+ align-items: center;
375
+ gap: 7px;
376
+ margin-bottom: 5px;
377
+ }
378
+ .tool-dot {
379
+ width: 5px; height: 5px; border-radius: 50%;
380
+ background: #9a9a9a;
381
+ display: inline-block;
382
+ flex-shrink: 0;
383
+ }
384
+ .tool-io {
385
+ font-family: 'JetBrains Mono', monospace;
386
+ font-size: 0.78em;
387
+ color: var(--fg-dim);
388
+ padding: 2px 0;
389
+ word-break: break-word;
390
+ white-space: pre-wrap;
391
+ }
392
+ .io-label {
393
+ color: var(--fg-dimmer);
394
+ margin-right: 8px;
395
+ }
396
+ .tool-error .tool-head { color: #d8d8d8; }
397
+ .tool-error { border-left-color: #555; }
398
+
399
+ /* ---------- çalışıyor göstergesi ---------- */
400
+ .status-line {
401
+ display: flex;
402
+ align-items: center;
403
+ gap: 8px;
404
+ color: var(--fg-dimmer);
405
+ font-size: 0.8em;
406
+ margin-top: 8px;
407
+ font-style: italic;
408
+ }
409
+ .pulse-dot {
410
+ width: 6px; height: 6px; border-radius: 50%;
411
+ background: var(--fg-dim);
412
+ animation: pulse 1.2s ease-in-out infinite;
413
+ flex-shrink: 0;
414
+ }
415
+ @keyframes pulse { 0%, 100% { opacity: .2; } 50% { opacity: 1; } }
416
+
417
+ /* ---------- örnek baloncukları (textbox'ın üstünde, küçük) ---------- */
418
+ .examples-row { margin-bottom: 8px !important; gap: 6px !important; }
419
+ .bubble-btn {
420
+ background: transparent !important;
421
+ border: 1px solid #2c2c2c !important;
422
+ border-radius: 999px !important;
423
+ color: var(--fg-dim) !important;
424
+ font-size: 0.76em !important;
425
+ font-weight: 400 !important;
426
+ padding: 5px 14px !important;
427
+ min-width: auto !important;
428
+ flex-grow: 0 !important;
429
+ box-shadow: none !important;
430
+ transition: color .15s ease, border-color .15s ease;
431
+ }
432
+ .bubble-btn:hover {
433
+ color: #fff !important;
434
+ border-color: #6a6a6a !important;
435
+ }
436
+
437
+ /* ---------- mesaj kutusu ---------- */
438
+ #msg_box textarea {
439
+ background: transparent !important;
440
+ border: none !important;
441
+ border-bottom: 1px solid #2a2a2a !important;
442
+ border-radius: 0 !important;
443
+ color: var(--fg) !important;
444
+ padding: 10px 4px !important;
445
+ font-size: 0.95em !important;
446
+ }
447
+ #msg_box textarea:focus {
448
+ border-bottom-color: #808080 !important;
449
+ box-shadow: none !important;
450
+ }
451
+ #msg_box textarea::placeholder { color: #555 !important; }
452
+
453
+ #submit_btn {
454
+ background: transparent !important;
455
+ color: var(--fg) !important;
456
+ border: 1px solid #333 !important;
457
+ border-radius: 999px !important;
458
+ font-weight: 400 !important;
459
+ }
460
+ #submit_btn:hover { border-color: #7a7a7a !important; color: #fff !important; }
461
  """
462
 
463
  with gr.Blocks(theme=gr.themes.Base(), css=css) as demo:
464
+ gr.Markdown(
465
+ "<div class='header-wrap'>"
466
+ "<div class='header-title'>🌍 AFET TAKİP</div>"
467
+ "<div class='header-sub'>agentic disaster intelligence</div>"
468
+ "</div>"
469
+ )
470
+
471
+ chatbot = gr.Chatbot(elem_id="chatbot", height=520, label="Asistan", show_label=False)
472
+
473
+ with gr.Row(elem_classes="examples-row"):
474
+ ex1 = gr.Button("son depremler", elem_classes="bubble-btn")
475
+ ex2 = gr.Button("aktif yangınlar", elem_classes="bubble-btn")
476
+ ex3 = gr.Button("deprem + yangın birleştir", elem_classes="bubble-btn")
477
 
478
  with gr.Row():
479
  msg = gr.Textbox(placeholder="Afetlerle ilgili ne öğrenmek istersiniz?", label="Mesajınız", lines=1, show_label=False, elem_id="msg_box", scale=4)
480
  submit_btn = gr.Button("Gönder", variant="primary", scale=1, elem_id="submit_btn")
481
+
482
  ex1.click(lambda: "2026-07-25 ile 2026-07-30 tarihleri arasındaki 5.5 üzeri depremleri listele.", outputs=msg)
483
  ex2.click(lambda: "Şu anki aktif büyük orman yangınları hangileri? 3 tanesini getir.", outputs=msg)
484
  ex3.click(lambda: "Son 7 günde (2026-07-23 ile 2026-07-30) 6.0'dan büyük deprem oldu mu? Ayrıca şu an aktif orman yangını var mı?", outputs=msg)
485
+
486
  def respond(user_message, chat_history):
487
  # Arayüze kullanıcının mesajını ekle
488
  chat_history.append((user_message, ""))
489
+
490
  # Jeneratörden gelen kısımları adım adım güncelle
491
  for bot_message in chat_interface(user_message, chat_history[:-1]):
492
  chat_history[-1] = (user_message, bot_message)
 
496
  msg.submit(respond, [msg, chatbot], [chatbot, msg], api_name=False)
497
 
498
  if __name__ == "__main__":
499
+ demo.launch()