markobinario commited on
Commit
4b7f251
·
verified ·
1 Parent(s): 684d7a1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -74
app.py CHANGED
@@ -429,6 +429,58 @@ Just type your question or start a conversation, and I'll do my best to help you
429
 
430
  return None
431
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
  def fetch_from_database(self, question: str) -> str:
433
  """Fetch answer from the database with smart matching"""
434
  try:
@@ -447,56 +499,66 @@ Just type your question or start a conversation, and I'll do my best to help you
447
  # Fallback to original method if smart matching doesn't work
448
  endpoints = [
449
  f"{self.database_url}/faqs",
 
450
  f"{self.database_url}/search",
451
  f"{self.database_url}/query",
452
  f"{self.database_url}/api/faq"
453
  ]
454
-
 
 
 
455
  for endpoint in endpoints:
456
- try:
457
- # Try GET request with query parameter
458
- response = requests.get(endpoint, params={"question": question}, timeout=10)
459
- if response.status_code == 200:
460
- data = response.json()
461
- if isinstance(data, dict):
462
- answer = data.get('answer', data.get('response', str(data)))
463
- # Check if we got a meaningful answer
464
- if answer and answer.strip() and not self._is_no_answer_response(answer):
465
- return answer
466
- elif isinstance(data, list) and len(data) > 0:
467
- answer = str(data[0])
468
- if answer and answer.strip() and not self._is_no_answer_response(answer):
469
- return answer
470
- else:
471
- answer = str(data)
472
- if answer and answer.strip() and not self._is_no_answer_response(answer):
473
- return answer
474
- except:
475
- try:
476
- # Try POST request with JSON body
477
- response = requests.post(
478
- endpoint,
479
- json={"question": question},
480
- headers={"Content-Type": "application/json"},
481
- timeout=10
482
- )
483
- if response.status_code == 200:
484
- data = response.json()
485
- if isinstance(data, dict):
486
- answer = data.get('answer', data.get('response', str(data)))
487
- # Check if we got a meaningful answer
488
- if answer and answer.strip() and not self._is_no_answer_response(answer):
489
- return answer
490
- elif isinstance(data, list) and len(data) > 0:
491
- answer = str(data[0])
492
- if answer and answer.strip() and not self._is_no_answer_response(answer):
493
- return answer
494
- else:
495
- answer = str(data)
496
- if answer and answer.strip() and not self._is_no_answer_response(answer):
497
- return answer
498
- except:
499
- continue
 
 
 
 
 
 
500
 
501
  # If no answer found, save the question as unanswered
502
  saved = self.save_unanswered_question(question)
@@ -559,40 +621,51 @@ Just type your question or start a conversation, and I'll do my best to help you
559
  try:
560
  endpoints = [
561
  f"{self.database_url}/faqs",
 
562
  f"{self.database_url}/search",
563
  f"{self.database_url}/query",
564
  f"{self.database_url}/api/faq"
565
  ]
566
-
 
 
 
567
  for endpoint in endpoints:
568
- try:
569
- response = requests.get(endpoint, params={"question": question}, timeout=10)
570
- if response.status_code == 200:
571
- data = response.json()
572
- if isinstance(data, dict):
573
- return data.get('answer', data.get('response', str(data)))
574
- elif isinstance(data, list) and len(data) > 0:
575
- return str(data[0])
576
- else:
577
- return str(data)
578
- except:
579
- try:
580
- response = requests.post(
581
- endpoint,
582
- json={"question": question},
583
- headers={"Content-Type": "application/json"},
584
- timeout=10
585
- )
586
- if response.status_code == 200:
587
- data = response.json()
588
- if isinstance(data, dict):
589
- return data.get('answer', data.get('response', str(data)))
590
- elif isinstance(data, list) and len(data) > 0:
591
- return str(data[0])
592
- else:
593
- return str(data)
594
- except:
595
- continue
 
 
 
 
 
 
 
596
 
597
  return None
598
  except:
 
429
 
430
  return None
431
 
432
+ def _generate_query_variants(self, question: str) -> List[str]:
433
+ """Generate lightweight query variants to improve matching against FAQs"""
434
+ variants: List[str] = []
435
+ original = question.strip()
436
+ variants.append(original)
437
+
438
+ # Normalized
439
+ norm = self._normalize_text(original)
440
+ variants.append(norm)
441
+
442
+ # Remove trailing punctuation and repeated spaces already handled by normalize
443
+
444
+ # Simple lemmatization-ish tweaks for common cases
445
+ rules = [
446
+ (r"\btakes\b", "take"),
447
+ (r"\btake\b", "takes"),
448
+ (r"\bdoes\b", "do"),
449
+ (r"\bdo\b", "does"),
450
+ (r"\bis\b", "are"),
451
+ (r"\bare\b", "is"),
452
+ ]
453
+
454
+ for pattern, repl in rules:
455
+ try:
456
+ v = re.sub(pattern, repl, norm)
457
+ if v not in variants:
458
+ variants.append(v)
459
+ except Exception:
460
+ pass
461
+
462
+ # Last-word singular/plural toggle
463
+ words = norm.split()
464
+ if words:
465
+ last = words[-1]
466
+ if len(last) > 3 and last.endswith('s'):
467
+ alt = ' '.join(words[:-1] + [last[:-1]])
468
+ if alt not in variants:
469
+ variants.append(alt)
470
+ else:
471
+ alt = ' '.join(words[:-1] + [last + 's'])
472
+ if alt not in variants:
473
+ variants.append(alt)
474
+
475
+ # De-duplicate while preserving order
476
+ seen = set()
477
+ unique_variants: List[str] = []
478
+ for v in variants:
479
+ if v not in seen and v:
480
+ seen.add(v)
481
+ unique_variants.append(v)
482
+ return unique_variants
483
+
484
  def fetch_from_database(self, question: str) -> str:
485
  """Fetch answer from the database with smart matching"""
486
  try:
 
499
  # Fallback to original method if smart matching doesn't work
500
  endpoints = [
501
  f"{self.database_url}/faqs",
502
+ f"{self.database_url}/faq",
503
  f"{self.database_url}/search",
504
  f"{self.database_url}/query",
505
  f"{self.database_url}/api/faq"
506
  ]
507
+
508
+ param_names = ["question", "q"]
509
+ variants = self._generate_query_variants(question)
510
+
511
  for endpoint in endpoints:
512
+ for variant in variants:
513
+ for param_name in param_names:
514
+ # Try GET
515
+ try:
516
+ response = requests.get(
517
+ endpoint,
518
+ params={param_name: variant},
519
+ timeout=10
520
+ )
521
+ if response.status_code == 200:
522
+ data = response.json()
523
+ if isinstance(data, dict):
524
+ answer = data.get('answer', data.get('response', str(data)))
525
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
526
+ return answer
527
+ elif isinstance(data, list) and len(data) > 0:
528
+ answer = str(data[0])
529
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
530
+ return answer
531
+ else:
532
+ answer = str(data)
533
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
534
+ return answer
535
+ except Exception:
536
+ pass
537
+
538
+ # Try POST JSON
539
+ try:
540
+ response = requests.post(
541
+ endpoint,
542
+ json={param_name: variant},
543
+ headers={"Content-Type": "application/json"},
544
+ timeout=10
545
+ )
546
+ if response.status_code == 200:
547
+ data = response.json()
548
+ if isinstance(data, dict):
549
+ answer = data.get('answer', data.get('response', str(data)))
550
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
551
+ return answer
552
+ elif isinstance(data, list) and len(data) > 0:
553
+ answer = str(data[0])
554
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
555
+ return answer
556
+ else:
557
+ answer = str(data)
558
+ if answer and answer.strip() and not self._is_no_answer_response(answer):
559
+ return answer
560
+ except Exception:
561
+ pass
562
 
563
  # If no answer found, save the question as unanswered
564
  saved = self.save_unanswered_question(question)
 
621
  try:
622
  endpoints = [
623
  f"{self.database_url}/faqs",
624
+ f"{self.database_url}/faq",
625
  f"{self.database_url}/search",
626
  f"{self.database_url}/query",
627
  f"{self.database_url}/api/faq"
628
  ]
629
+
630
+ param_names = ["question", "q"]
631
+ variants = self._generate_query_variants(question)
632
+
633
  for endpoint in endpoints:
634
+ for variant in variants:
635
+ for param_name in param_names:
636
+ try:
637
+ response = requests.get(
638
+ endpoint,
639
+ params={param_name: variant},
640
+ timeout=10
641
+ )
642
+ if response.status_code == 200:
643
+ data = response.json()
644
+ if isinstance(data, dict):
645
+ return data.get('answer', data.get('response', str(data)))
646
+ elif isinstance(data, list) and len(data) > 0:
647
+ return str(data[0])
648
+ else:
649
+ return str(data)
650
+ except Exception:
651
+ pass
652
+ try:
653
+ response = requests.post(
654
+ endpoint,
655
+ json={param_name: variant},
656
+ headers={"Content-Type": "application/json"},
657
+ timeout=10
658
+ )
659
+ if response.status_code == 200:
660
+ data = response.json()
661
+ if isinstance(data, dict):
662
+ return data.get('answer', data.get('response', str(data)))
663
+ elif isinstance(data, list) and len(data) > 0:
664
+ return str(data[0])
665
+ else:
666
+ return str(data)
667
+ except Exception:
668
+ pass
669
 
670
  return None
671
  except: