Spaces:
Running
Running
Update reg_embedding_system.py
Browse files- reg_embedding_system.py +26 -26
reg_embedding_system.py
CHANGED
|
@@ -207,9 +207,9 @@ def load_embedding_from_faiss(
|
|
| 207 |
embeddings=embeddings,
|
| 208 |
allow_dangerous_deserialization=True
|
| 209 |
)
|
| 210 |
-
|
| 211 |
except Exception as e:
|
| 212 |
-
|
| 213 |
raise
|
| 214 |
|
| 215 |
# 3) BM25를 위한 문서 추출
|
|
@@ -218,7 +218,7 @@ def load_embedding_from_faiss(
|
|
| 218 |
if hasattr(vectorstore, "docstore") and hasattr(vectorstore.docstore, "_dict"):
|
| 219 |
docs = list(vectorstore.docstore._dict.values())
|
| 220 |
except Exception as e:
|
| 221 |
-
|
| 222 |
|
| 223 |
# 4) 앙상블 리트리버 구성
|
| 224 |
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": top_k})
|
|
@@ -231,7 +231,7 @@ def load_embedding_from_faiss(
|
|
| 231 |
weights=list(weights)
|
| 232 |
)
|
| 233 |
else:
|
| 234 |
-
|
| 235 |
ensemble_retriever = vector_retriever
|
| 236 |
|
| 237 |
# 5) SQLite 연결
|
|
@@ -266,8 +266,8 @@ def search_with_metadata_filter(
|
|
| 266 |
params = []
|
| 267 |
|
| 268 |
for key, value in metadata_filter.items():
|
| 269 |
-
|
| 270 |
-
|
| 271 |
if isinstance(value, list):
|
| 272 |
if not value:
|
| 273 |
continue
|
|
@@ -285,14 +285,14 @@ def search_with_metadata_filter(
|
|
| 285 |
try:
|
| 286 |
cursor.execute(sql_query, params)
|
| 287 |
filtered_ids = {row[0] for row in cursor.fetchall()}
|
| 288 |
-
|
| 289 |
except Exception as e:
|
| 290 |
-
|
| 291 |
filtered_ids = None
|
| 292 |
else:
|
| 293 |
-
|
| 294 |
else:
|
| 295 |
-
|
| 296 |
|
| 297 |
# === 2. FAISS 벡터 검색 ===
|
| 298 |
if filtered_ids and len(filtered_ids) > 0:
|
|
@@ -321,11 +321,11 @@ def search_with_metadata_filter(
|
|
| 321 |
if isinstance(doc, Document):
|
| 322 |
vector_docs.append(doc)
|
| 323 |
|
| 324 |
-
|
| 325 |
else:
|
| 326 |
search_k = k * 5
|
| 327 |
vector_docs = vector_ret.invoke(query, config={"search_kwargs": {"k": search_k}})
|
| 328 |
-
|
| 329 |
|
| 330 |
# === 3. BM25 검색 ===
|
| 331 |
bm25_docs = []
|
|
@@ -336,13 +336,13 @@ def search_with_metadata_filter(
|
|
| 336 |
bm25_docs = [d for d in candidates if d.metadata.get('faiss_id') in filtered_ids]
|
| 337 |
else:
|
| 338 |
bm25_docs = candidates[:k]
|
| 339 |
-
|
| 340 |
|
| 341 |
# === 4. 병합 및 최종 k개 반환 ===
|
| 342 |
combined = {id(d): d for d in (vector_docs + bm25_docs)}.values()
|
| 343 |
final_results = list(combined)[:k]
|
| 344 |
|
| 345 |
-
|
| 346 |
return final_results
|
| 347 |
|
| 348 |
def get_unique_metadata_values(
|
|
@@ -352,7 +352,7 @@ def get_unique_metadata_values(
|
|
| 352 |
) -> List[str]:
|
| 353 |
"""SQLite에서 특정 컬럼의 고유한 값 리스트를 반환합니다."""
|
| 354 |
if not sqlite_conn:
|
| 355 |
-
|
| 356 |
return []
|
| 357 |
|
| 358 |
cursor = sqlite_conn.cursor()
|
|
@@ -368,10 +368,10 @@ def get_unique_metadata_values(
|
|
| 368 |
unique_values = [row[0] for row in cursor.fetchall() if row[0] is not None]
|
| 369 |
return unique_values
|
| 370 |
except sqlite3.OperationalError as e:
|
| 371 |
-
|
| 372 |
return []
|
| 373 |
except Exception as e:
|
| 374 |
-
|
| 375 |
return []
|
| 376 |
|
| 377 |
def smart_search_vectorstore(
|
|
@@ -386,10 +386,10 @@ def smart_search_vectorstore(
|
|
| 386 |
# 1. 기본 검색
|
| 387 |
basic_results = retriever.invoke(query)
|
| 388 |
basic_results = basic_results[:k]
|
| 389 |
-
|
| 390 |
|
| 391 |
if not enable_detailed_search or not vectorstore or not sqlite_conn:
|
| 392 |
-
|
| 393 |
return basic_results
|
| 394 |
|
| 395 |
# 2. regulation_part 빈도 분석
|
|
@@ -406,18 +406,18 @@ def smart_search_vectorstore(
|
|
| 406 |
regulation_parts.append(reg_part)
|
| 407 |
|
| 408 |
if not regulation_parts:
|
| 409 |
-
|
| 410 |
return basic_results
|
| 411 |
|
| 412 |
counter = Counter(regulation_parts)
|
| 413 |
most_extracted_category = counter.most_common(2)
|
| 414 |
-
|
| 415 |
-
|
| 416 |
|
| 417 |
# 3. 상세 검색
|
| 418 |
detailed_results = []
|
| 419 |
for rank, (category, count) in enumerate(most_extracted_category, 1):
|
| 420 |
-
|
| 421 |
metadata_filter = {'regulation_part': category}
|
| 422 |
|
| 423 |
try:
|
|
@@ -430,9 +430,9 @@ def smart_search_vectorstore(
|
|
| 430 |
sqlite_conn=sqlite_conn
|
| 431 |
)
|
| 432 |
detailed_results.extend(category_results)
|
| 433 |
-
|
| 434 |
except Exception as e:
|
| 435 |
-
|
| 436 |
continue
|
| 437 |
|
| 438 |
# 4. 결과 병합
|
|
@@ -452,7 +452,7 @@ def smart_search_vectorstore(
|
|
| 452 |
final_results.append(doc)
|
| 453 |
|
| 454 |
final_results = final_results[:k]
|
| 455 |
-
|
| 456 |
|
| 457 |
return final_results
|
| 458 |
|
|
|
|
| 207 |
embeddings=embeddings,
|
| 208 |
allow_dangerous_deserialization=True
|
| 209 |
)
|
| 210 |
+
logger.info(f"[로드 성공] FAISS 인덱스 로드 완료: {persist_dir}")
|
| 211 |
except Exception as e:
|
| 212 |
+
logger.info(f"[로드 오류] FAISS 로드 실패: {e}")
|
| 213 |
raise
|
| 214 |
|
| 215 |
# 3) BM25를 위한 문서 추출
|
|
|
|
| 218 |
if hasattr(vectorstore, "docstore") and hasattr(vectorstore.docstore, "_dict"):
|
| 219 |
docs = list(vectorstore.docstore._dict.values())
|
| 220 |
except Exception as e:
|
| 221 |
+
logger.info(f"[경고] 저장된 문서를 읽는 중 문제가 발생했습니다: {e}")
|
| 222 |
|
| 223 |
# 4) 앙상블 리트리버 구성
|
| 224 |
vector_retriever = vectorstore.as_retriever(search_kwargs={"k": top_k})
|
|
|
|
| 231 |
weights=list(weights)
|
| 232 |
)
|
| 233 |
else:
|
| 234 |
+
logger.info("[안내] 문서를 찾지 못해 BM25 없이 벡터 리트리버만 반환합니다.")
|
| 235 |
ensemble_retriever = vector_retriever
|
| 236 |
|
| 237 |
# 5) SQLite 연결
|
|
|
|
| 266 |
params = []
|
| 267 |
|
| 268 |
for key, value in metadata_filter.items():
|
| 269 |
+
logger.info(f"[key] {key}")
|
| 270 |
+
logger.info(f"[value] {value}")
|
| 271 |
if isinstance(value, list):
|
| 272 |
if not value:
|
| 273 |
continue
|
|
|
|
| 285 |
try:
|
| 286 |
cursor.execute(sql_query, params)
|
| 287 |
filtered_ids = {row[0] for row in cursor.fetchall()}
|
| 288 |
+
logger.info(f"[사전 필터링] {len(filtered_ids)}개 ID 획득 → FAISS 검색 제한")
|
| 289 |
except Exception as e:
|
| 290 |
+
logger.info(f"[경고] SQLite 필터링 실패: {e}")
|
| 291 |
filtered_ids = None
|
| 292 |
else:
|
| 293 |
+
logger.info("[안내] 필터 조건 없음 → 전체 검색")
|
| 294 |
else:
|
| 295 |
+
logger.info("[안내] 필터 또는 DB 없음 → 전체 검색")
|
| 296 |
|
| 297 |
# === 2. FAISS 벡터 검색 ===
|
| 298 |
if filtered_ids and len(filtered_ids) > 0:
|
|
|
|
| 321 |
if isinstance(doc, Document):
|
| 322 |
vector_docs.append(doc)
|
| 323 |
|
| 324 |
+
logger.info(f"[벡터 검색] {len(valid_indices)}개 후보 → {len(vector_docs)}개 유효")
|
| 325 |
else:
|
| 326 |
search_k = k * 5
|
| 327 |
vector_docs = vector_ret.invoke(query, config={"search_kwargs": {"k": search_k}})
|
| 328 |
+
logger.info(f"[벡터 검색] 전체 검색 → {len(vector_docs)}개 후보")
|
| 329 |
|
| 330 |
# === 3. BM25 검색 ===
|
| 331 |
bm25_docs = []
|
|
|
|
| 336 |
bm25_docs = [d for d in candidates if d.metadata.get('faiss_id') in filtered_ids]
|
| 337 |
else:
|
| 338 |
bm25_docs = candidates[:k]
|
| 339 |
+
logger.info(f"[BM25 검색] {len(candidates)}개 후보 → {len(bm25_docs)}개 필터링 후")
|
| 340 |
|
| 341 |
# === 4. 병합 및 최종 k개 반환 ===
|
| 342 |
combined = {id(d): d for d in (vector_docs + bm25_docs)}.values()
|
| 343 |
final_results = list(combined)[:k]
|
| 344 |
|
| 345 |
+
logger.info(f"[최종 결과] {len(final_results)}개 문서 반환")
|
| 346 |
return final_results
|
| 347 |
|
| 348 |
def get_unique_metadata_values(
|
|
|
|
| 352 |
) -> List[str]:
|
| 353 |
"""SQLite에서 특정 컬럼의 고유한 값 리스트를 반환합니다."""
|
| 354 |
if not sqlite_conn:
|
| 355 |
+
logger.info("[경고] SQLite 연결이 없어 고유 값 검색을 수행할 수 없습니다.")
|
| 356 |
return []
|
| 357 |
|
| 358 |
cursor = sqlite_conn.cursor()
|
|
|
|
| 368 |
unique_values = [row[0] for row in cursor.fetchall() if row[0] is not None]
|
| 369 |
return unique_values
|
| 370 |
except sqlite3.OperationalError as e:
|
| 371 |
+
logger.info(f"[에러] SQLite 쿼리 실행 실패 (컬럼 '{key_name}' 이름 오류 가능): {e}")
|
| 372 |
return []
|
| 373 |
except Exception as e:
|
| 374 |
+
logger.info(f"[에러] 고유 값 검색 중 알 수 없는 오류 발생: {e}")
|
| 375 |
return []
|
| 376 |
|
| 377 |
def smart_search_vectorstore(
|
|
|
|
| 386 |
# 1. 기본 검색
|
| 387 |
basic_results = retriever.invoke(query)
|
| 388 |
basic_results = basic_results[:k]
|
| 389 |
+
logger.info(f"[기본 검색] {len(basic_results)}개 문서 검색 완료")
|
| 390 |
|
| 391 |
if not enable_detailed_search or not vectorstore or not sqlite_conn:
|
| 392 |
+
logger.info("[안내] 상세 검색 비활성화 또는 컴포넌트 부족 → 기본 검색 결과만 반환")
|
| 393 |
return basic_results
|
| 394 |
|
| 395 |
# 2. regulation_part 빈도 분석
|
|
|
|
| 406 |
regulation_parts.append(reg_part)
|
| 407 |
|
| 408 |
if not regulation_parts:
|
| 409 |
+
logger.info("[안내] regulation_part 메타데이터 없음 → 기본 검색 결과만 반환")
|
| 410 |
return basic_results
|
| 411 |
|
| 412 |
counter = Counter(regulation_parts)
|
| 413 |
most_extracted_category = counter.most_common(2)
|
| 414 |
+
logger.info(f"[빈도 분석] regulation_part 빈도: {dict(counter)}")
|
| 415 |
+
logger.info(f"[상위 카테고리] {most_extracted_category}")
|
| 416 |
|
| 417 |
# 3. 상세 검색
|
| 418 |
detailed_results = []
|
| 419 |
for rank, (category, count) in enumerate(most_extracted_category, 1):
|
| 420 |
+
logger.info(f"[상세 검색 {rank}순위] '{category}' 카테고리 검색 시작 (빈도: {count})")
|
| 421 |
metadata_filter = {'regulation_part': category}
|
| 422 |
|
| 423 |
try:
|
|
|
|
| 430 |
sqlite_conn=sqlite_conn
|
| 431 |
)
|
| 432 |
detailed_results.extend(category_results)
|
| 433 |
+
logger.info(f"[상세 검색 {rank}순위] {len(category_results)}개 추가 문서 검색 완료")
|
| 434 |
except Exception as e:
|
| 435 |
+
logger.info(f"[경고] 상세 검색 {rank}순위 실패 ({category}): {e}")
|
| 436 |
continue
|
| 437 |
|
| 438 |
# 4. 결과 병합
|
|
|
|
| 452 |
final_results.append(doc)
|
| 453 |
|
| 454 |
final_results = final_results[:k]
|
| 455 |
+
logger.info(f"[최종 결과] 기본 {len(basic_results)}개 + 상세 {len(detailed_results)}개 → 중복 제거 후 {len(final_results)}개 반환")
|
| 456 |
|
| 457 |
return final_results
|
| 458 |
|