AI_Menu_Search / scripts /23_weight_grid.py
Juhaha
HF Spaces 데모 배포 (Streamlit + Qdrant 임베디드, 색인 빌드타임 생성)
fbd1091
Raw
History Blame Contribute Delete
2.82 kB
"""
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()