decodingdatascience commited on
Commit
2855ba4
·
verified ·
1 Parent(s): 88a94a3

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -149
app.py CHANGED
@@ -171,8 +171,7 @@ if INDEX_NAME not in existing_indexes:
171
  else:
172
 
173
  logger.info(
174
- "Existing Pinecone index found. "
175
- "NOT deleting it."
176
  )
177
 
178
 
@@ -238,47 +237,39 @@ if vector_count == 0:
238
  }
239
  ).load_data()
240
 
241
-
242
  if not documents:
243
 
244
  raise ValueError(
245
  "No PDF documents found inside Data folder"
246
  )
247
 
248
-
249
  logger.info(
250
  f"Loaded {len(documents)} document sections"
251
  )
252
 
253
-
254
  storage_context = StorageContext.from_defaults(
255
  vector_store=vector_store
256
  )
257
 
258
-
259
  logger.info(
260
  "Creating embeddings and storing them in Pinecone..."
261
  )
262
 
263
-
264
  index = VectorStoreIndex.from_documents(
265
  documents,
266
  storage_context=storage_context,
267
  )
268
 
269
-
270
  logger.info(
271
  "DDS HR Handbook indexed successfully."
272
  )
273
 
274
-
275
  else:
276
 
277
  logger.info(
278
  "Using existing Pinecone vectors."
279
  )
280
 
281
-
282
  index = VectorStoreIndex.from_vector_store(
283
  vector_store=vector_store
284
  )
@@ -302,19 +293,15 @@ def query_doc(question):
302
  if not question:
303
  return "Please enter an HR question."
304
 
305
-
306
  question = question.strip()
307
 
308
-
309
  if not question:
310
  return "Please enter an HR question."
311
 
312
-
313
  logger.info(
314
  f"HR question received: {question}"
315
  )
316
 
317
-
318
  try:
319
 
320
  response = query_engine.query(
@@ -329,7 +316,6 @@ def query_doc(question):
329
 
330
  return answer
331
 
332
-
333
  except Exception as e:
334
 
335
  logger.exception(
@@ -343,7 +329,7 @@ def query_doc(question):
343
 
344
 
345
  # ============================================================
346
- # 12. TELEGRAM FUNCTIONS
347
  # ============================================================
348
 
349
  def telegram_url(method):
@@ -356,37 +342,52 @@ def telegram_url(method):
356
 
357
 
358
  # ============================================================
359
- # 13. TEST TELEGRAM CONNECTION
360
  # ============================================================
361
 
362
  def test_telegram_connection():
363
 
364
  if not TELEGRAM_BOT_TOKEN:
 
 
 
 
 
365
  return False
366
 
 
 
 
 
 
 
 
 
 
 
 
367
 
368
  try:
369
 
370
  response = requests.get(
371
  telegram_url("getMe"),
372
- timeout=10
 
 
 
 
373
  )
374
 
375
  response.raise_for_status()
376
 
377
  data = response.json()
378
 
379
-
380
  if data.get("ok"):
381
 
382
  bot = data["result"]
383
 
384
  logger.info(
385
- "===================================="
386
- )
387
-
388
- logger.info(
389
- "TELEGRAM CONNECTED"
390
  )
391
 
392
  logger.info(
@@ -403,18 +404,32 @@ def test_telegram_connection():
403
 
404
  return True
405
 
 
 
 
 
 
 
 
406
 
407
  logger.error(
408
- f"Telegram rejected token: {data}"
409
  )
410
 
411
  return False
412
 
 
 
 
 
 
 
 
413
 
414
  except Exception as e:
415
 
416
  logger.exception(
417
- f"Telegram connection error: {e}"
418
  )
419
 
420
  return False
@@ -424,55 +439,35 @@ def test_telegram_connection():
424
  # 14. SEND TELEGRAM MESSAGE
425
  # ============================================================
426
 
427
- def send_telegram_message(
428
- chat_id,
429
- text
430
- ):
431
 
432
  if not TELEGRAM_BOT_TOKEN:
433
  return
434
 
435
-
436
  text = str(text)
437
 
438
-
439
- # Telegram messages have a length limit,
440
- # so split long answers.
441
  chunks = [
442
-
443
  text[i:i + 4000]
444
-
445
- for i in range(
446
- 0,
447
- len(text),
448
- 4000
449
- )
450
-
451
  ]
452
 
453
-
454
  for chunk in chunks:
455
 
456
  try:
457
 
458
  response = requests.post(
459
-
460
- telegram_url(
461
- "sendMessage"
462
- ),
463
-
464
  json={
465
  "chat_id": chat_id,
466
  "text": chunk,
467
  },
468
-
469
- timeout=15
470
  )
471
 
472
-
473
  response.raise_for_status()
474
 
475
-
476
  except Exception as e:
477
 
478
  logger.exception(
@@ -481,7 +476,7 @@ def send_telegram_message(
481
 
482
 
483
  # ============================================================
484
- # 15. SHOW TYPING...
485
  # ============================================================
486
 
487
  def telegram_typing(chat_id):
@@ -489,31 +484,21 @@ def telegram_typing(chat_id):
489
  try:
490
 
491
  requests.post(
492
-
493
- telegram_url(
494
- "sendChatAction"
495
- ),
496
-
497
  json={
498
  "chat_id": chat_id,
499
  "action": "typing",
500
  },
501
-
502
- timeout=5
503
  )
504
 
505
-
506
  except Exception:
507
 
508
  pass
509
 
510
 
511
  # ============================================================
512
- # 16. TELEGRAM POLLING
513
- #
514
- # IMPORTANT:
515
- # We deliberately use SHORT POLLING for this demo.
516
- # This avoids the 55-second Hugging Face timeout you saw.
517
  # ============================================================
518
 
519
  def telegram_polling_loop():
@@ -527,10 +512,9 @@ def telegram_polling_loop():
527
 
528
  return
529
 
530
-
531
- # ----------------------------------------------
532
- # Verify token first
533
- # ----------------------------------------------
534
 
535
  if not test_telegram_connection():
536
 
@@ -538,35 +522,33 @@ def telegram_polling_loop():
538
  "Telegram connection failed."
539
  )
540
 
 
 
 
 
541
  return
542
 
543
 
544
- # ----------------------------------------------
545
- # Delete old webhook
546
- # getUpdates will not work with a webhook active.
547
- # ----------------------------------------------
548
 
549
  try:
550
 
551
- requests.post(
552
-
553
- telegram_url(
554
- "deleteWebhook"
555
- ),
556
-
557
  json={
558
  "drop_pending_updates": True
559
  },
560
-
561
- timeout=10
562
  )
563
 
 
564
 
565
  logger.info(
566
  "Old Telegram webhook cleared."
567
  )
568
 
569
-
570
  except Exception as e:
571
 
572
  logger.warning(
@@ -574,6 +556,10 @@ def telegram_polling_loop():
574
  )
575
 
576
 
 
 
 
 
577
  logger.info(
578
  "===================================="
579
  )
@@ -602,28 +588,18 @@ def telegram_polling_loop():
602
  "timeout": 0
603
  }
604
 
605
-
606
  if offset is not None:
607
-
608
  params["offset"] = offset
609
 
610
 
611
- # SHORT POLLING
612
  response = requests.get(
613
-
614
- telegram_url(
615
- "getUpdates"
616
- ),
617
-
618
  params=params,
619
-
620
- timeout=10
621
  )
622
 
623
-
624
  response.raise_for_status()
625
 
626
-
627
  data = response.json()
628
 
629
 
@@ -647,18 +623,14 @@ def telegram_polling_loop():
647
  for update in updates:
648
 
649
  offset = (
650
- update["update_id"]
651
- + 1
652
  )
653
 
654
-
655
  message = update.get(
656
  "message"
657
  )
658
 
659
-
660
  if not message:
661
-
662
  continue
663
 
664
 
@@ -667,12 +639,10 @@ def telegram_polling_loop():
667
  {}
668
  )
669
 
670
-
671
  chat_id = chat.get(
672
  "id"
673
  )
674
 
675
-
676
  text = (
677
  message.get(
678
  "text"
@@ -682,19 +652,15 @@ def telegram_polling_loop():
682
 
683
 
684
  if not chat_id:
685
-
686
  continue
687
 
688
 
689
  if not text:
690
 
691
  send_telegram_message(
692
-
693
  chat_id,
694
-
695
  "Please send me a text "
696
  "question about DDS HR policies."
697
-
698
  )
699
 
700
  continue
@@ -705,102 +671,83 @@ def telegram_polling_loop():
705
  )
706
 
707
 
708
- # ==================================
709
  # /start
710
- # ==================================
711
 
712
- if text.startswith(
713
- "/start"
714
- ):
715
 
716
  send_telegram_message(
717
-
718
  chat_id,
719
-
720
  "Welcome to AYesha — "
721
  "DDS Enterprise HR Chatbot.\n\n"
722
  "Ask me a question about the "
723
  "latest DDS HR policies.\n\n"
724
  "For example:\n"
725
  "What is the annual leave policy?"
726
-
727
  )
728
 
729
  continue
730
 
731
 
732
- # ==================================
733
  # /help
734
- # ==================================
735
 
736
- if text.startswith(
737
- "/help"
738
- ):
739
 
740
  send_telegram_message(
741
-
742
  chat_id,
743
-
744
  "Ask me questions about DDS HR "
745
  "policies.\n\n"
746
  "Examples:\n"
747
  "• What is the annual leave policy?\n"
748
  "• What is the probation policy?\n"
749
  "• How do I request leave?"
750
-
751
  )
752
 
753
  continue
754
 
755
 
756
- # ==================================
757
  # OTHER COMMAND
758
- # ==================================
759
 
760
  if text.startswith("/"):
761
 
762
  send_telegram_message(
763
-
764
  chat_id,
765
-
766
  "Please type your HR question "
767
  "as a normal message."
768
-
769
  )
770
 
771
  continue
772
 
773
 
774
- # ==================================
775
  # NORMAL HR QUESTION
776
- # ==================================
777
 
778
  telegram_typing(
779
  chat_id
780
  )
781
 
782
-
783
  answer = query_doc(
784
  text
785
  )
786
 
787
-
788
  send_telegram_message(
789
-
790
  chat_id,
791
  answer
792
-
793
  )
794
 
795
 
796
- # Prevent aggressive API calling
797
  time.sleep(1)
798
 
799
 
800
  except requests.exceptions.Timeout:
801
 
802
- # Network timeout is not fatal.
803
- # Simply try again.
804
  logger.warning(
805
  "Telegram temporary timeout. Retrying..."
806
  )
@@ -840,21 +787,14 @@ def start_telegram_bot():
840
 
841
  return
842
 
843
-
844
  thread = threading.Thread(
845
-
846
  target=telegram_polling_loop,
847
-
848
  daemon=True,
849
-
850
  name="DDS-Telegram-Bot"
851
-
852
  )
853
 
854
-
855
  thread.start()
856
 
857
-
858
  logger.info(
859
  "Telegram background thread started."
860
  )
@@ -876,13 +816,10 @@ demo = gr.Interface(
876
  fn=query_doc,
877
 
878
  inputs=gr.Textbox(
879
-
880
  label="Ask a question about DDS HR policies",
881
-
882
  placeholder=(
883
  "Example: What is the annual leave policy?"
884
  )
885
-
886
  ),
887
 
888
  outputs=gr.Textbox(
@@ -906,9 +843,6 @@ demo = gr.Interface(
906
  if __name__ == "__main__":
907
 
908
  demo.launch(
909
-
910
  server_name="0.0.0.0",
911
-
912
  server_port=7860
913
-
914
  )
 
171
  else:
172
 
173
  logger.info(
174
+ "Existing Pinecone index found. NOT deleting it."
 
175
  )
176
 
177
 
 
237
  }
238
  ).load_data()
239
 
 
240
  if not documents:
241
 
242
  raise ValueError(
243
  "No PDF documents found inside Data folder"
244
  )
245
 
 
246
  logger.info(
247
  f"Loaded {len(documents)} document sections"
248
  )
249
 
 
250
  storage_context = StorageContext.from_defaults(
251
  vector_store=vector_store
252
  )
253
 
 
254
  logger.info(
255
  "Creating embeddings and storing them in Pinecone..."
256
  )
257
 
 
258
  index = VectorStoreIndex.from_documents(
259
  documents,
260
  storage_context=storage_context,
261
  )
262
 
 
263
  logger.info(
264
  "DDS HR Handbook indexed successfully."
265
  )
266
 
 
267
  else:
268
 
269
  logger.info(
270
  "Using existing Pinecone vectors."
271
  )
272
 
 
273
  index = VectorStoreIndex.from_vector_store(
274
  vector_store=vector_store
275
  )
 
293
  if not question:
294
  return "Please enter an HR question."
295
 
 
296
  question = question.strip()
297
 
 
298
  if not question:
299
  return "Please enter an HR question."
300
 
 
301
  logger.info(
302
  f"HR question received: {question}"
303
  )
304
 
 
305
  try:
306
 
307
  response = query_engine.query(
 
316
 
317
  return answer
318
 
 
319
  except Exception as e:
320
 
321
  logger.exception(
 
329
 
330
 
331
  # ============================================================
332
+ # 12. TELEGRAM URL
333
  # ============================================================
334
 
335
  def telegram_url(method):
 
342
 
343
 
344
  # ============================================================
345
+ # 13. TEST TELEGRAM CONNECTION FROM HUGGING FACE
346
  # ============================================================
347
 
348
  def test_telegram_connection():
349
 
350
  if not TELEGRAM_BOT_TOKEN:
351
+
352
+ logger.error(
353
+ "TELEGRAM TEST: Token is missing."
354
+ )
355
+
356
  return False
357
 
358
+ logger.info(
359
+ "===================================="
360
+ )
361
+
362
+ logger.info(
363
+ "TESTING HUGGING FACE -> TELEGRAM"
364
+ )
365
+
366
+ logger.info(
367
+ f"TELEGRAM TOKEN FOUND: {bool(TELEGRAM_BOT_TOKEN)}"
368
+ )
369
 
370
  try:
371
 
372
  response = requests.get(
373
  telegram_url("getMe"),
374
+ timeout=30
375
+ )
376
+
377
+ logger.info(
378
+ f"TELEGRAM TEST STATUS: {response.status_code}"
379
  )
380
 
381
  response.raise_for_status()
382
 
383
  data = response.json()
384
 
 
385
  if data.get("ok"):
386
 
387
  bot = data["result"]
388
 
389
  logger.info(
390
+ "TELEGRAM TEST RESULT: SUCCESS"
 
 
 
 
391
  )
392
 
393
  logger.info(
 
404
 
405
  return True
406
 
407
+ logger.error(
408
+ f"TELEGRAM TEST RESULT: API ERROR: {data}"
409
+ )
410
+
411
+ return False
412
+
413
+ except requests.exceptions.Timeout as e:
414
 
415
  logger.error(
416
+ f"TELEGRAM TEST FAILED: TIMEOUT: {repr(e)}"
417
  )
418
 
419
  return False
420
 
421
+ except requests.exceptions.RequestException as e:
422
+
423
+ logger.error(
424
+ f"TELEGRAM TEST FAILED: NETWORK ERROR: {repr(e)}"
425
+ )
426
+
427
+ return False
428
 
429
  except Exception as e:
430
 
431
  logger.exception(
432
+ f"TELEGRAM TEST FAILED: {repr(e)}"
433
  )
434
 
435
  return False
 
439
  # 14. SEND TELEGRAM MESSAGE
440
  # ============================================================
441
 
442
+ def send_telegram_message(chat_id, text):
 
 
 
443
 
444
  if not TELEGRAM_BOT_TOKEN:
445
  return
446
 
 
447
  text = str(text)
448
 
449
+ # Telegram messages have a length limit.
450
+ # Split long answers into smaller pieces.
 
451
  chunks = [
 
452
  text[i:i + 4000]
453
+ for i in range(0, len(text), 4000)
 
 
 
 
 
 
454
  ]
455
 
 
456
  for chunk in chunks:
457
 
458
  try:
459
 
460
  response = requests.post(
461
+ telegram_url("sendMessage"),
 
 
 
 
462
  json={
463
  "chat_id": chat_id,
464
  "text": chunk,
465
  },
466
+ timeout=30
 
467
  )
468
 
 
469
  response.raise_for_status()
470
 
 
471
  except Exception as e:
472
 
473
  logger.exception(
 
476
 
477
 
478
  # ============================================================
479
+ # 15. SHOW TELEGRAM TYPING
480
  # ============================================================
481
 
482
  def telegram_typing(chat_id):
 
484
  try:
485
 
486
  requests.post(
487
+ telegram_url("sendChatAction"),
 
 
 
 
488
  json={
489
  "chat_id": chat_id,
490
  "action": "typing",
491
  },
492
+ timeout=10
 
493
  )
494
 
 
495
  except Exception:
496
 
497
  pass
498
 
499
 
500
  # ============================================================
501
+ # 16. TELEGRAM POLLING LOOP
 
 
 
 
502
  # ============================================================
503
 
504
  def telegram_polling_loop():
 
512
 
513
  return
514
 
515
+ # --------------------------------------------------------
516
+ # STEP 1: TEST HUGGING FACE -> TELEGRAM
517
+ # --------------------------------------------------------
 
518
 
519
  if not test_telegram_connection():
520
 
 
522
  "Telegram connection failed."
523
  )
524
 
525
+ logger.error(
526
+ "Web chatbot will continue running normally."
527
+ )
528
+
529
  return
530
 
531
 
532
+ # --------------------------------------------------------
533
+ # STEP 2: DELETE ANY OLD WEBHOOK
534
+ # --------------------------------------------------------
 
535
 
536
  try:
537
 
538
+ response = requests.post(
539
+ telegram_url("deleteWebhook"),
 
 
 
 
540
  json={
541
  "drop_pending_updates": True
542
  },
543
+ timeout=30
 
544
  )
545
 
546
+ response.raise_for_status()
547
 
548
  logger.info(
549
  "Old Telegram webhook cleared."
550
  )
551
 
 
552
  except Exception as e:
553
 
554
  logger.warning(
 
556
  )
557
 
558
 
559
+ # --------------------------------------------------------
560
+ # STEP 3: START LISTENING FOR TELEGRAM MESSAGES
561
+ # --------------------------------------------------------
562
+
563
  logger.info(
564
  "===================================="
565
  )
 
588
  "timeout": 0
589
  }
590
 
 
591
  if offset is not None:
 
592
  params["offset"] = offset
593
 
594
 
 
595
  response = requests.get(
596
+ telegram_url("getUpdates"),
 
 
 
 
597
  params=params,
598
+ timeout=30
 
599
  )
600
 
 
601
  response.raise_for_status()
602
 
 
603
  data = response.json()
604
 
605
 
 
623
  for update in updates:
624
 
625
  offset = (
626
+ update["update_id"] + 1
 
627
  )
628
 
 
629
  message = update.get(
630
  "message"
631
  )
632
 
 
633
  if not message:
 
634
  continue
635
 
636
 
 
639
  {}
640
  )
641
 
 
642
  chat_id = chat.get(
643
  "id"
644
  )
645
 
 
646
  text = (
647
  message.get(
648
  "text"
 
652
 
653
 
654
  if not chat_id:
 
655
  continue
656
 
657
 
658
  if not text:
659
 
660
  send_telegram_message(
 
661
  chat_id,
 
662
  "Please send me a text "
663
  "question about DDS HR policies."
 
664
  )
665
 
666
  continue
 
671
  )
672
 
673
 
674
+ # ============================================
675
  # /start
676
+ # ============================================
677
 
678
+ if text.startswith("/start"):
 
 
679
 
680
  send_telegram_message(
 
681
  chat_id,
 
682
  "Welcome to AYesha — "
683
  "DDS Enterprise HR Chatbot.\n\n"
684
  "Ask me a question about the "
685
  "latest DDS HR policies.\n\n"
686
  "For example:\n"
687
  "What is the annual leave policy?"
 
688
  )
689
 
690
  continue
691
 
692
 
693
+ # ============================================
694
  # /help
695
+ # ============================================
696
 
697
+ if text.startswith("/help"):
 
 
698
 
699
  send_telegram_message(
 
700
  chat_id,
 
701
  "Ask me questions about DDS HR "
702
  "policies.\n\n"
703
  "Examples:\n"
704
  "• What is the annual leave policy?\n"
705
  "• What is the probation policy?\n"
706
  "• How do I request leave?"
 
707
  )
708
 
709
  continue
710
 
711
 
712
+ # ============================================
713
  # OTHER COMMAND
714
+ # ============================================
715
 
716
  if text.startswith("/"):
717
 
718
  send_telegram_message(
 
719
  chat_id,
 
720
  "Please type your HR question "
721
  "as a normal message."
 
722
  )
723
 
724
  continue
725
 
726
 
727
+ # ============================================
728
  # NORMAL HR QUESTION
729
+ # ============================================
730
 
731
  telegram_typing(
732
  chat_id
733
  )
734
 
 
735
  answer = query_doc(
736
  text
737
  )
738
 
 
739
  send_telegram_message(
 
740
  chat_id,
741
  answer
 
742
  )
743
 
744
 
745
+ # Prevent aggressive Telegram API calls
746
  time.sleep(1)
747
 
748
 
749
  except requests.exceptions.Timeout:
750
 
 
 
751
  logger.warning(
752
  "Telegram temporary timeout. Retrying..."
753
  )
 
787
 
788
  return
789
 
 
790
  thread = threading.Thread(
 
791
  target=telegram_polling_loop,
 
792
  daemon=True,
 
793
  name="DDS-Telegram-Bot"
 
794
  )
795
 
 
796
  thread.start()
797
 
 
798
  logger.info(
799
  "Telegram background thread started."
800
  )
 
816
  fn=query_doc,
817
 
818
  inputs=gr.Textbox(
 
819
  label="Ask a question about DDS HR policies",
 
820
  placeholder=(
821
  "Example: What is the annual leave policy?"
822
  )
 
823
  ),
824
 
825
  outputs=gr.Textbox(
 
843
  if __name__ == "__main__":
844
 
845
  demo.launch(
 
846
  server_name="0.0.0.0",
 
847
  server_port=7860
 
848
  )