From c2a02ce514baa89455862b19ff188b36a2b95543 Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Tue, 1 Sep 2026 11:19:09 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20AI=20Discovery=20=EB=9E=AD=ED=82=B9=20?= =?UTF-8?q?=EC=8B=9C=ED=8A=B8=20TOP20=20=E2=86=92=20TOP50=20=ED=99=95?= =?UTF-8?q?=EC=9E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_0155BJMHJyhqqAPGYjGKYhPS --- docs/reports/Viewclinic_QB_Results.xlsx | Bin 207726 -> 209033 bytes scripts/export_qb_excel.py | 14 +++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/reports/Viewclinic_QB_Results.xlsx b/docs/reports/Viewclinic_QB_Results.xlsx index 837e8a0ec4acccf3b088eb97a0a3f72f6d9fcb7f..806810991b472b96d80df186189bc9f7a2357e31 100644 GIT binary patch delta 4561 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 delta 3189 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 Q0P&6(z)#gA2$1{#0o{vzmjD0& diff --git a/scripts/export_qb_excel.py b/scripts/export_qb_excel.py index bf1ced5..389b8ed 100644 --- a/scripts/export_qb_excel.py +++ b/scripts/export_qb_excel.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 """Question Bank 120문항 + 2엔진 실측 결과를 엑셀(xlsx)로 내보낸다. -시트: 요약 / 통합결과 / 병원빈도 / TOP20 / GPT상세 / PPLX상세 +시트: 요약 / 통합결과 / 병원빈도 / TOP50 / GPT상세 / PPLX상세 """ import json import os @@ -146,8 +146,8 @@ def main(): ws.column_dimensions[col].width = w # ── TOP20 (논브랜드 84문항 · 2엔진 합산 랭킹) ───────── - ws = wb.create_sheet("TOP20") - ws["A1"] = "성형외과 AI Discovery TOP 20 (논브랜드 84문항 · ChatGPT+Perplexity 합산)" + ws = wb.create_sheet("TOP50") + ws["A1"] = "성형외과 AI Discovery TOP 50 (논브랜드 84문항 · ChatGPT+Perplexity 합산)" ws["A1"].font = Font(bold=True, size=14, color=INK) ws["A2"] = "점수 = 답변 내 등장 순위 가중치(1위 5점 ~ 5위 1점)를 질문·엔진 단위로 합산. 브랜드 직접 질문 36문항은 제외." ws["A2"].font = Font(size=10, color="666B7A") @@ -179,11 +179,11 @@ def main(): ranked = sorted(agg.values(), key=lambda a: (-a["score"], -a["first"], -(a["gpt"] + a["pplx"]))) view_rank = next((i + 1 for i, a in enumerate(ranked) if canon(a["label"]) == "뷰성형외과"), None) - shown = ranked[:20] - if view_rank and view_rank > 20: - shown = ranked[:20] + [ranked[view_rank - 1]] + shown = ranked[:50] + if view_rank and view_rank > 50: + shown = ranked[:50] + [ranked[view_rank - 1]] for idx, a in enumerate(shown): - rank = idx + 1 if idx < 20 else view_rank + rank = idx + 1 if idx < 50 else view_rank cats = " · ".join(k for k, _ in sorted(a["cats"].items(), key=lambda x: -x[1])[:3]) ws.append([rank, a["label"], a["score"], a["gpt"] + a["pplx"], a["gpt"], a["pplx"], a["first"], cats]) if canon(a["label"]) == "뷰성형외과":