Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -15,6 +15,8 @@ import re
|
|
| 15 |
import traceback
|
| 16 |
import requests # API 호출을 위해 필요
|
| 17 |
|
|
|
|
|
|
|
| 18 |
# --- Together AI SDK ---
|
| 19 |
from together import Together
|
| 20 |
|
|
@@ -315,22 +317,72 @@ def handle_cancel_search(data):
|
|
| 315 |
@app.route('/get_reg_list', methods=['POST'])
|
| 316 |
def get_reg_list():
|
| 317 |
data = request.get_json()
|
| 318 |
-
selected_regions = data.get('regions', [])
|
|
|
|
|
|
|
|
|
|
|
|
|
| 319 |
|
| 320 |
all_reg_list_part = []
|
|
|
|
|
|
|
|
|
|
|
|
|
| 321 |
for region in selected_regions:
|
| 322 |
rag = region_rag_objects.get(region)
|
| 323 |
if not rag:
|
| 324 |
-
continue
|
|
|
|
| 325 |
try:
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 329 |
except Exception as e:
|
| 330 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
|
| 332 |
-
|
| 333 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 334 |
|
| 335 |
# --- SocketIO ---
|
| 336 |
@socketio.on('connect')
|
|
@@ -566,6 +618,66 @@ def create_combined_filters(grouped_regulations):
|
|
| 566 |
|
| 567 |
return filters
|
| 568 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
# --- 실행 ---
|
| 570 |
if __name__ == '__main__':
|
| 571 |
# 로컬 개발용
|
|
|
|
| 15 |
import traceback
|
| 16 |
import requests # API 호출을 위해 필요
|
| 17 |
|
| 18 |
+
from typing import Optional, Tuple, Any, Dict, List
|
| 19 |
+
|
| 20 |
# --- Together AI SDK ---
|
| 21 |
from together import Together
|
| 22 |
|
|
|
|
| 317 |
@app.route('/get_reg_list', methods=['POST'])
|
| 318 |
def get_reg_list():
|
| 319 |
data = request.get_json()
|
| 320 |
+
selected_regions = data.get('regions', [])
|
| 321 |
+
|
| 322 |
+
# 지역이 선택되지 않았으면 전체 지역으로 설정
|
| 323 |
+
if not selected_regions:
|
| 324 |
+
selected_regions = ["국내", "북미", "유럽"]
|
| 325 |
|
| 326 |
all_reg_list_part = []
|
| 327 |
+
all_reg_list_section = []
|
| 328 |
+
all_reg_list_chapter = []
|
| 329 |
+
all_reg_list_jo = []
|
| 330 |
+
|
| 331 |
for region in selected_regions:
|
| 332 |
rag = region_rag_objects.get(region)
|
| 333 |
if not rag:
|
| 334 |
+
continue # 해당 지역 RAG가 없으면 건너뜀
|
| 335 |
+
|
| 336 |
try:
|
| 337 |
+
# 이미 로드된 SQLite 연결 재사용
|
| 338 |
+
sqlite_conn = rag["sqlite_conn"]
|
| 339 |
+
reg_list_part = get_unique_metadata_values(sqlite_conn, "regulation_part")
|
| 340 |
+
reg_list_section = get_unique_metadata_values(sqlite_conn, "regulation_section")
|
| 341 |
+
reg_list_chapter = get_unique_metadata_values(sqlite_conn, "chapter_section")
|
| 342 |
+
reg_list_jo = get_unique_metadata_values(sqlite_conn, "jo")
|
| 343 |
+
|
| 344 |
+
# 문자열이면 리스트로 변환
|
| 345 |
+
if isinstance(reg_list_part, str):
|
| 346 |
+
reg_list_part = [reg_list_part]
|
| 347 |
+
|
| 348 |
+
if isinstance(reg_list_section, str):
|
| 349 |
+
reg_list_section = [reg_list_section]
|
| 350 |
+
|
| 351 |
+
if isinstance(reg_list_chapter, str):
|
| 352 |
+
reg_list_chapter = [reg_list_chapter]
|
| 353 |
+
|
| 354 |
+
if isinstance(reg_list_jo, str):
|
| 355 |
+
reg_list_jo = [reg_list_jo]
|
| 356 |
+
|
| 357 |
+
all_reg_list_part.extend(reg_list_part)
|
| 358 |
+
all_reg_list_section.extend(reg_list_section)
|
| 359 |
+
all_reg_list_chapter.extend(reg_list_chapter)
|
| 360 |
+
all_reg_list_jo.extend(reg_list_jo)
|
| 361 |
except Exception as e:
|
| 362 |
+
print(f"[{region}] DB 연결 오류: {e}")
|
| 363 |
+
|
| 364 |
+
# 중복 제거
|
| 365 |
+
#unique_reg_list_part = list(set(all_reg_list_part))
|
| 366 |
+
unique_reg_list_part = sorted(set(all_reg_list_part), key=reg_embedding_system.natural_sort_key)
|
| 367 |
+
|
| 368 |
+
#unique_reg_list_section = list(set(all_reg_list_section))
|
| 369 |
+
unique_reg_list_section = sorted(set(all_reg_list_section), key=reg_embedding_system.natural_sort_key)
|
| 370 |
|
| 371 |
+
#unique_reg_list_chapter = list(set(all_reg_list_chapter))
|
| 372 |
+
unique_reg_list_chapter = sorted(set(all_reg_list_chapter), key=reg_embedding_system.natural_sort_key)
|
| 373 |
+
|
| 374 |
+
#unique_reg_list_jo = list(set(all_reg_list_jo))
|
| 375 |
+
unique_reg_list_jo = sorted(set(all_reg_list_jo), key=reg_embedding_system.natural_sort_key)
|
| 376 |
+
|
| 377 |
+
text_result_part = "\n".join(str(item) for item in unique_reg_list_part)
|
| 378 |
+
text_result_section = "\n".join(str(item) for item in unique_reg_list_section)
|
| 379 |
+
text_result_chapter = "\n".join(str(item) for item in unique_reg_list_chapter)
|
| 380 |
+
text_result_jo = "\n".join(str(item) for item in unique_reg_list_jo)
|
| 381 |
+
|
| 382 |
+
return jsonify(reg_list_part=text_result_part,
|
| 383 |
+
reg_list_section=text_result_section,
|
| 384 |
+
reg_list_chapter=text_result_chapter,
|
| 385 |
+
reg_list_jo=text_result_jo)
|
| 386 |
|
| 387 |
# --- SocketIO ---
|
| 388 |
@socketio.on('connect')
|
|
|
|
| 618 |
|
| 619 |
return filters
|
| 620 |
|
| 621 |
+
def natural_sort_key(text):
|
| 622 |
+
"""숫자가 포함된 문자열을 자연스럽게 정렬 (예: item1, item2, item10)"""
|
| 623 |
+
return [int(c) if c.isdigit() else c.lower() for c in re.split('([0-9]+)', str(text))]
|
| 624 |
+
|
| 625 |
+
def get_unique_metadata_values(
|
| 626 |
+
sqlite_conn: sqlite3.Connection,
|
| 627 |
+
key_name: str,
|
| 628 |
+
partial_match: Optional[str] = None
|
| 629 |
+
) -> List[str]:
|
| 630 |
+
"""
|
| 631 |
+
SQLite 'documents' 테이블에서 특정 컬럼(key_name)의 중복되지 않은
|
| 632 |
+
모든 고유 값 리스트를 반환합니다.
|
| 633 |
+
|
| 634 |
+
Args:
|
| 635 |
+
sqlite_conn: SQLite 데이터베이스 연결 객체.
|
| 636 |
+
key_name: 고유한 값을 가져올 컬럼 이름 (예: 'regulation_name', 'part_name').
|
| 637 |
+
partial_match: (선택 사항) 해당 문자열을 포함하는 값만 검색할 때 사용.
|
| 638 |
+
|
| 639 |
+
Returns:
|
| 640 |
+
중복이 제거된 고유한 값들의 리스트.
|
| 641 |
+
"""
|
| 642 |
+
|
| 643 |
+
text_result = ""
|
| 644 |
+
if not sqlite_conn:
|
| 645 |
+
print("[경고] SQLite 연결이 없어 고유 값 검색을 수행할 수 없습니다.")
|
| 646 |
+
return text_result
|
| 647 |
+
|
| 648 |
+
cursor = sqlite_conn.cursor()
|
| 649 |
+
|
| 650 |
+
# SQL 쿼리 ���성
|
| 651 |
+
# 1. 컬럼 이름에 백틱(`)을 사용하여 안전성 확보
|
| 652 |
+
# 2. DISTINCT를 사용하여 중복 제거
|
| 653 |
+
|
| 654 |
+
sql_query = f"SELECT DISTINCT `{key_name}` FROM documents"
|
| 655 |
+
params = []
|
| 656 |
+
|
| 657 |
+
# 부분 문자열 검색 (LIKE) 조건 추가
|
| 658 |
+
if partial_match:
|
| 659 |
+
sql_query += f" WHERE `{key_name}` LIKE ?"
|
| 660 |
+
params.append(f"%{partial_match}%")
|
| 661 |
+
|
| 662 |
+
try:
|
| 663 |
+
cursor.execute(sql_query, params)
|
| 664 |
+
|
| 665 |
+
# 쿼리 결과에서 첫 번째 항목 (값)만 추출
|
| 666 |
+
unique_values = [row[0] for row in cursor.fetchall() if row[0] is not None]
|
| 667 |
+
unique_values.sort(key=natural_sort_key)
|
| 668 |
+
text_result = "\n".join(str(value) for value in unique_values)
|
| 669 |
+
|
| 670 |
+
return text_result
|
| 671 |
+
|
| 672 |
+
except sqlite3.OperationalError as e:
|
| 673 |
+
# 컬럼 이름이 DB에 없을 때 발생하는 에러 처리
|
| 674 |
+
print(f"[에러] SQLite 쿼리 실행 실패 (컬럼 '{key_name}' 이름 오류 가능): {e}")
|
| 675 |
+
return text_result
|
| 676 |
+
except Exception as e:
|
| 677 |
+
print(f"[에러] 고유 값 검색 중 알 수 없는 오류 발생: {e}")
|
| 678 |
+
return text_result
|
| 679 |
+
|
| 680 |
+
|
| 681 |
# --- 실행 ---
|
| 682 |
if __name__ == '__main__':
|
| 683 |
# 로컬 개발용
|