Spaces:
Running
Running
| """ | |
| Dense/BM25 가중치 그리드 서치 | |
| =============================== | |
| 실행: | |
| .venv/Scripts/python.exe scripts/23_weight_grid.py | |
| """ | |
| import sys, re, json | |
| from pathlib import Path | |
| from collections import defaultdict | |
| sys.path.insert(0, str(Path(__file__).parent.parent)) | |
| import core.search_engine as se_mod | |
| from core.search_engine import MenuSearchEngine | |
| EVAL_PATH = Path(__file__).parent.parent / "data" / "eval_queries_300.json" | |
| def normalize_path(path): | |
| if not path: return '' | |
| path = re.sub(r'\s*>\s*', '>', str(path)) | |
| path = re.sub(r'\(.*?\)', '', path) | |
| return path.strip().lower() | |
| def matches(pred, ans): | |
| if not pred or not ans: return False | |
| if pred == ans: return True | |
| pred_end = pred.split('>')[-1].strip() | |
| ans_end = ans.split('>')[-1].strip() | |
| if pred_end and ans_end and pred_end == ans_end: | |
| pp = pred.split('>') | |
| ap = ans.split('>') | |
| return sum(1 for p in pp if p in ap) >= min(2, len(ap)) | |
| return False | |
| def run_eval(engine, eval_set, use_hyde=False): | |
| acc1, acc3, acc5, mrr_list = [], [], [], [] | |
| for item in eval_set: | |
| hits = engine.search(item['query'], top_n=5, threshold=0.0, use_hyde=use_hyde) | |
| paths = [normalize_path(h.get('menu_path', '')) for h in hits] | |
| ans = normalize_path(item['menu_path']) | |
| h1 = matches(paths[0], ans) if paths else False | |
| h3 = any(matches(p, ans) for p in paths[:3]) | |
| h5 = any(matches(p, ans) for p in paths[:5]) | |
| rr = next((1.0/k for k, p in enumerate(paths[:5], 1) if matches(p, ans)), 0.0) | |
| acc1.append(h1); acc3.append(h3); acc5.append(h5); mrr_list.append(rr) | |
| n = len(acc1) | |
| return { | |
| 'acc1': sum(acc1)/n, 'acc3': sum(acc3)/n, | |
| 'acc5': sum(acc5)/n, 'mrr': sum(mrr_list)/n, 'n': n, | |
| } | |
| def main(): | |
| with open(EVAL_PATH, encoding='utf-8') as f: | |
| eval_set = json.load(f) | |
| print(f"평가셋: {len(eval_set)}개") | |
| print("검색엔진 초기화 중...") | |
| engine = MenuSearchEngine.get_instance() | |
| print("준비 완료\n") | |
| configs = [ | |
| ('Dense=1.5 BM25=0.5 (현재)', 1.5, 0.5), | |
| ('Dense=1.0 BM25=1.0 (동등)', 1.0, 1.0), | |
| ('Dense=1.0 BM25=1.5 (BM25↑)', 1.0, 1.5), | |
| ('Dense=1.2 BM25=0.8 (중간)', 1.2, 0.8), | |
| ] | |
| print(f"{'설정':<28} {'Acc@1':>6} {'Acc@3':>6} {'Acc@5':>6} {'MRR':>6}") | |
| print("-" * 60) | |
| for label, w_d, w_b in configs: | |
| se_mod.W_DENSE = w_d | |
| se_mod.W_BM25 = w_b | |
| r = run_eval(engine, eval_set, use_hyde=False) | |
| print(f" {label:<26} {r['acc1']:>5.1%} {r['acc3']:>6.1%} {r['acc5']:>6.1%} {r['mrr']:>6.3f}") | |
| # 원래 값 복원 | |
| se_mod.W_DENSE = 1.5 | |
| se_mod.W_BM25 = 0.5 | |
| print("\n가중치 원복 완료 (Dense=1.5, BM25=0.5)") | |
| if __name__ == "__main__": | |
| main() | |