Spaces:
Running
Running
| """ | |
| HTS 도메인 특화 규칙 기반 쿼리 확장기 (QueryExpander) | |
| - LLM 없음 → 10ms 이내 실행 | |
| - HTS 핵심 용어 동의어 사전으로 쿼리 확장 | |
| - BM25 검색에서 사용 (Dense 임베딩에는 사용 안 함) | |
| 사용 예: | |
| expander = QueryExpander() | |
| expander.expand("주문 취소") | |
| # → "주문 취소 매수 매도 거래 체결 미체결 정정 주문변경" | |
| """ | |
| from typing import List | |
| # --------------------------------------------------------------------------- | |
| # HTS 도메인 동의어 사전 | |
| # 키: 원본 단어, 값: 함께 추가할 관련어 리스트 (원본 포함) | |
| # --------------------------------------------------------------------------- | |
| SYNONYM_MAP = { | |
| # ── 주문 계열 ────────────────────────────────────────────────────────── | |
| "취소": ["취소", "정정", "주문변경", "미체결", "주문취소", "정정취소"], | |
| "정정": ["정정", "취소", "수정", "변경", "주문변경", "주문수정"], | |
| "주문": ["주문", "매수", "매도", "거래", "체결", "미체결"], | |
| "매수": ["매수", "사다", "구매", "주문", "체결"], | |
| "매도": ["매도", "팔다", "판매", "주문", "체결"], | |
| "사고": ["매수", "사다", "구매", "주문"], | |
| "팔고": ["매도", "팔다", "판매", "주문"], | |
| "예약": ["예약", "예약주문", "자동주문", "시간지정", "걸어놓다"], | |
| "일괄": ["일괄", "묶음", "동시", "한꺼번에", "대량주문"], | |
| "자동": ["자동", "예약", "예약주문", "자동주문", "걸어놓다"], | |
| "걸어": ["예약", "예약주문", "자동주문", "걸어놓다"], | |
| # ── 잔고 / 손익 계열 ─────────────────────────────────────────────────── | |
| "잔고": ["잔고", "보유", "수량", "평가금액", "자산", "보유주식"], | |
| "손익": ["손익", "수익", "수익률", "평가손익", "실현손익"], | |
| "수익": ["수익", "손익", "수익률", "평가손익", "이익", "수익현황"], | |
| "얼마": ["잔고", "평가금액", "수익률", "손익", "잔고조회", "수익", "보유"], | |
| "올랐": ["손익", "수익률", "평가손익", "수익", "잔고"], | |
| "내렸": ["손익", "평가손익", "손실", "수익률"], | |
| "보유": ["보유", "잔고", "내주식", "포트폴리오", "보유주식"], | |
| "주식": ["주식", "잔고", "보유주식", "주식잔고", "국내주식잔고"], | |
| "확인": ["확인", "조회", "잔고확인", "현황", "조회하다"], | |
| "내주식": ["잔고", "보유주식", "국내잔고", "수익", "평가금액"], | |
| # ── 시세 계열 ────────────────────────────────────────────────────────── | |
| "시세": ["시세", "현재가", "가격", "주가", "호가", "실시간"], | |
| "현재가": ["현재가", "시세", "실시간", "주가", "체결가"], | |
| "가격": ["현재가", "시세", "주가", "호가", "체결가"], | |
| "호가": ["호가", "체결", "호가창", "매수호가", "매도호가"], | |
| "체결": ["체결", "호가", "체결내역", "체결가", "거래"], | |
| # "지금"은 자연어 시간 강조 표현 — 현재가/시세로 확장 시 잔고 쿼리에서 역효과 | |
| # 예: "지금 내 주식 얼마야" → 호가로 오매칭. BM25 자체 IDF로 처리. | |
| # "지금": ["현재가", "실시간", "시세", "주가"], # 비활성화 | |
| # ── 차트 계열 ────────────────────────────────────────────────────────── | |
| "차트": ["차트", "일봉", "주봉", "캔들", "그래프", "시세차트"], | |
| "일봉": ["일봉", "차트", "일별시세", "캔들차트", "주봉"], | |
| "그래프": ["차트", "그래프", "일봉", "캔들"], | |
| # ── 조건검색 계열 ────────────────────────────────────────────────────── | |
| "조건": ["조건", "조건검색", "스크리닝", "필터", "검색식"], | |
| "스크리닝": ["스크리닝", "조건검색", "종목검색", "필터", "조건"], | |
| "검색식": ["검색식", "조건검색", "조건식", "스크리닝"], | |
| "실시간": ["실시간", "조건검색", "현재가", "시세"], | |
| # ── 자산 / 계좌 계열 ─────────────────────────────────────────────────── | |
| "이체": ["이체", "계좌이체", "자금이동", "송금", "계좌간이체"], | |
| "계좌": ["계좌", "잔고", "자산", "통합조회", "계좌잔고"], | |
| "자산": ["자산", "계좌", "잔고", "포트폴리오", "통합조회"], | |
| "통합": ["통합", "통합조회", "계좌잔고", "자산", "전체"], | |
| "송금": ["이체", "계좌이체", "자금이동", "송금"], | |
| # ── 투자정보 계열 ────────────────────────────────────────────────────── | |
| "공시": ["공시", "전자공시", "공시검색", "사업보고서", "기업공시"], | |
| "뉴스": ["뉴스", "종목뉴스", "시장정보", "이슈", "뉴스검색"], | |
| "정보": ["투자정보", "뉴스", "공시", "시장정보"], | |
| # ── 설정 계열 ────────────────────────────────────────────────────────── | |
| "알림": ["알림", "푸시", "푸시알림", "알림설정", "알림끄기"], | |
| "푸시": ["푸시", "알림", "푸시알림", "알림설정"], | |
| "설정": ["설정", "환경설정", "화면설정", "알림설정"], | |
| "끄기": ["해제", "알림해제", "알림끄기", "알림설정"], | |
| # ── 해외주식 계열 ────────────────────────────────────────────────────── | |
| "해외": ["해외", "미국", "해외주식", "글로벌", "나스닥"], | |
| "미국": ["미국", "해외", "나스닥", "NYSE", "미국주식", "해외주식"], | |
| "나스닥": ["나스닥", "미국", "해외주식", "NYSE"], | |
| # ── 선물/옵션 계열 ──────────────────────────────────────────────────── | |
| "선물": ["선물", "선물주문", "선물옵션", "파생", "futures"], | |
| "옵션": ["옵션", "선물옵션", "파생상품", "선물"], | |
| } | |
| class QueryExpander: | |
| """ | |
| 짧은 HTS 검색 쿼리를 도메인 동의어로 확장. | |
| BM25 검색 전처리에 사용. Dense 임베딩에는 사용하지 않음. | |
| Args: | |
| max_extra_terms: 추가할 최대 동의어 수 (기본 8개) | |
| 너무 많으면 BM25 IDF 점수 희석 | |
| 사용 예:: | |
| expander = QueryExpander() | |
| print(expander.expand("주문 취소하고 싶어")) | |
| # "주문 취소하고 싶어 매수 매도 거래 정정 주문변경 미체결" | |
| print(expander.get_expansion_terms("차트 보여줘")) | |
| # ["일봉", "주봉", "캔들", "그래프", "시세차트"] | |
| """ | |
| def __init__(self, max_extra_terms: int = 8): | |
| self.synonym_map = SYNONYM_MAP | |
| self.max_extra_terms = max_extra_terms | |
| def expand(self, query: str) -> str: | |
| """ | |
| 쿼리에서 등장하는 키워드를 동의어로 확장. | |
| 원본 쿼리를 앞에 유지하고, 동의어를 뒤에 추가. | |
| 공백 기반 토큰 단위로 처리 (형태소 분석 없음). | |
| Returns: | |
| 확장된 쿼리 문자열 | |
| """ | |
| tokens = query.strip().split() | |
| extra_terms: List[str] = [] | |
| seen = set(tokens) | |
| for token in tokens: | |
| if token in self.synonym_map: | |
| for synonym in self.synonym_map[token]: | |
| if synonym not in seen: | |
| extra_terms.append(synonym) | |
| seen.add(synonym) | |
| if len(extra_terms) >= self.max_extra_terms: | |
| break | |
| if len(extra_terms) >= self.max_extra_terms: | |
| break | |
| if extra_terms: | |
| return query + " " + " ".join(extra_terms) | |
| return query | |
| def get_expansion_terms(self, query: str) -> List[str]: | |
| """확장 용어 목록만 반환 (디버깅/로깅용)""" | |
| original_tokens = set(query.strip().split()) | |
| expanded = self.expand(query) | |
| all_tokens = expanded.split() | |
| return [t for t in all_tokens if t not in original_tokens] | |