scipious commited on
Commit
1fb6cfd
·
verified ·
1 Parent(s): bad7edf

Update reg_embedding_system_v02.py

Browse files
Files changed (1) hide show
  1. reg_embedding_system_v02.py +55 -42
reg_embedding_system_v02.py CHANGED
@@ -454,54 +454,67 @@ def get_unique_metadata_values(
454
  return []
455
 
456
  def smart_search_vectorstore(
457
- retriever,
 
458
  query,
459
  k=5,
460
- vectorstore=None,
461
  sqlite_conn=None,
462
  enable_detailed_search=True
463
  ):
464
- """기본 검색 + 상세 검색 수행"""
465
- # 1. 기본 검색
466
- basic_results = retriever.invoke(query)
467
- basic_results = basic_results[:k]
468
- #logger.info(f"[기본 검색] {len(basic_results)}개 문서 검색 완료")
469
 
470
- if not enable_detailed_search or not vectorstore or not sqlite_conn:
471
- #logger.info("[안내] 상세 검색 비활성화 또는 컴포넌트 부족 → 기본 검색 결과만 반환")
 
 
 
 
 
 
 
 
 
472
  return basic_results
473
 
474
- # 2. regulation_part 빈도 분석
475
- regulation_parts = []
 
 
 
476
  for doc in basic_results:
477
- reg_part = doc.metadata.get('regulation_part')
478
- if reg_part:
479
- if isinstance(reg_part, list):
480
- regulation_parts.extend(reg_part)
481
- elif isinstance(reg_part, str):
482
- if ',' in reg_part:
483
- regulation_parts.extend([part.strip() for part in reg_part.split(',')])
 
484
  else:
485
- regulation_parts.append(reg_part)
486
 
487
- if not regulation_parts:
488
- #logger.info("[안내] regulation_part 메타데이터 없음 기본 검색 결과만 반환")
489
  return basic_results
490
 
491
- counter = Counter(regulation_parts)
492
- most_extracted_category = counter.most_common(2)
493
- #logger.info(f"[빈도 분석] regulation_part 빈도: {dict(counter)}")
494
- #logger.info(f"[상위 카테고리] {most_extracted_category}")
495
 
496
- # 3. 상세 검색
497
  detailed_results = []
498
- for rank, (category, count) in enumerate(most_extracted_category, 1):
499
- #logger.info(f"[상세 검색 {rank}순위] '{category}' 카테고리 검색 시작 (빈도: {count})")
500
- metadata_filter = {'regulation_part': category}
501
 
502
  try:
 
503
  category_results = search_with_metadata_filter(
504
- ensemble_retriever=retriever,
505
  vectorstore=vectorstore,
506
  query=query,
507
  k=k,
@@ -509,30 +522,30 @@ def smart_search_vectorstore(
509
  sqlite_conn=sqlite_conn
510
  )
511
  detailed_results.extend(category_results)
512
- #logger.info(f"[상세 검색 {rank}순위] {len(category_results)}개 추가 문서 검색 완료")
 
513
  except Exception as e:
514
- #logger.info(f"[경고] 상세 검색 {rank}순위 실패 ({category}): {e}")
515
  continue
516
 
517
- # 4. 결과 병합
 
518
  seen = set()
519
  final_results = []
520
 
521
- #Detailed 검색 결과를 먼저 추가
522
- for doc in detailed_results:
523
- doc_signature = (doc.page_content, str(sorted(doc.metadata.items())))
524
- if doc_signature not in seen:
525
- seen.add(doc_signature)
526
- final_results.append(doc)
527
-
528
- for doc in basic_results:
529
  doc_signature = (doc.page_content, str(sorted(doc.metadata.items())))
 
530
  if doc_signature not in seen:
531
  seen.add(doc_signature)
532
  final_results.append(doc)
533
 
 
534
  final_results = final_results[:k]
535
- #logger.info(f"[최종 결과] 기본 {len(basic_results)}개 + 상세 {len(detailed_results)}개 → 중복 제거 후 {len(final_results)}개 반환")
536
 
537
  return final_results
538
 
 
454
  return []
455
 
456
  def smart_search_vectorstore(
457
+ bm25_retriever,
458
+ vectorstore,
459
  query,
460
  k=5,
 
461
  sqlite_conn=None,
462
  enable_detailed_search=True
463
  ):
464
+ """
465
+ 1단계: 하이브리드 검색으로 전체 맥락 파악
466
+ 2단계: 검색된 문서들에서 주된 'regulation'(규정) 파악
467
+ 3단계: 해당 규정으로 필터링하여 심층 검색 수행
468
+ """
469
 
470
+ # 1. 기본 검색 (하이브리드 검색 수행)
471
+ # 단순 retriever.invoke가 아니라 앞서 정의한 search_vectorstore를 사용하여
472
+ # Vector + BM25 결과를 섞어서 가져옵니다.
473
+ try:
474
+ basic_results = search_vectorstore(bm25_retriever, vectorstore, query, k=k)
475
+ except Exception as e:
476
+ print(f"[스마트 검색 오류] 기본 검색 실패: {e}")
477
+ return []
478
+
479
+ # 상세 검색이 비활성화되었거나 필수 컴포넌트가 없으면 기본 결과 반환
480
+ if not enable_detailed_search or not sqlite_conn:
481
  return basic_results
482
 
483
+ # 2. 메타데이터 빈도 분석 (타겟 키: 'regulation')
484
+ # DB 스키마가 변경되었으므로 regulation_part 대신 regulation을 사용합니다.
485
+ target_metadata_key = 'regulation'
486
+ extracted_values = []
487
+
488
  for doc in basic_results:
489
+ val = doc.metadata.get(target_metadata_key)
490
+ if val:
491
+ if isinstance(val, list):
492
+ extracted_values.extend(val)
493
+ elif isinstance(val, str):
494
+ # DB 저장 시 ', ' 합쳐진 문자열일 수 있으므로 분리 시도
495
+ if ',' in val:
496
+ extracted_values.extend([part.strip() for part in val.split(',')])
497
  else:
498
+ extracted_values.append(val)
499
 
500
+ if not extracted_values:
501
+ # 분석할 메타데이터가 없으면 기본 결과 반환
502
  return basic_results
503
 
504
+ counter = Counter(extracted_values)
505
+ # 상위 2개의 카테고리(규정) 추출
506
+ most_common_categories = counter.most_common(2)
 
507
 
508
+ # 3. 상세 검색 (필터링 검색)
509
  detailed_results = []
510
+ for rank, (category, count) in enumerate(most_common_categories, 1):
511
+ # 상위 카테고리에 대해 필터링 조건 생성
512
+ metadata_filter = {target_metadata_key: category}
513
 
514
  try:
515
+ # 변경된 search_with_metadata_filter 시그니처에 맞춰 호출
516
  category_results = search_with_metadata_filter(
517
+ bm25_retriever=bm25_retriever, # [변경] Ensemble 대신 BM25 전달
518
  vectorstore=vectorstore,
519
  query=query,
520
  k=k,
 
522
  sqlite_conn=sqlite_conn
523
  )
524
  detailed_results.extend(category_results)
525
+ print(f"[스마트 검색] '{category}' 집중 검색 → {len(category_results)}개 추가")
526
+
527
  except Exception as e:
528
+ print(f"[경고] 상세 검색 실패 ({category}): {e}")
529
  continue
530
 
531
+ # 4. 결과 병합 및 중복 제거
532
+ # (상세 검색 결과 우선 + 기본 검색 결과)
533
  seen = set()
534
  final_results = []
535
 
536
+ # 우선순위: 상세 검색 결과 -> 기본 검색 결과
537
+ all_candidates = detailed_results + basic_results
538
+
539
+ for doc in all_candidates:
540
+ # 문서 내용과 메타데이터 문자열을 조합하여 고유 키 생성
 
 
 
541
  doc_signature = (doc.page_content, str(sorted(doc.metadata.items())))
542
+
543
  if doc_signature not in seen:
544
  seen.add(doc_signature)
545
  final_results.append(doc)
546
 
547
+ # 최종적으로 k개만 반환
548
  final_results = final_results[:k]
 
549
 
550
  return final_results
551