From f2fe99b81d8d34e15d5ab94407ca3afa8cadda1d Mon Sep 17 00:00:00 2001 From: Haewon Kam Date: Tue, 15 Sep 2026 09:36:33 +0900 Subject: [PATCH] =?UTF-8?q?docs(reports):=20=EB=8B=B5=EB=B3=80=EC=97=94?= =?UTF-8?q?=EC=A7=84=20=ED=99=95=EC=9E=A5=20=EA=B2=80=ED=86=A0=20=EB=B3=B4?= =?UTF-8?q?=EA=B3=A0=EC=84=9C=20(120=EB=AC=B8=ED=95=AD=20=EB=B9=84?= =?UTF-8?q?=EC=9A=A9=20=EC=B6=94=EC=A0=95=C2=B7=ED=9B=84=EB=B3=B4=EB=B3=84?= =?UTF-8?q?=20=EC=95=BD=EA=B4=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5 (1M context) --- docs/reports/README.md | 1 + ...INFINITH_답변엔진_확장검토_2026-09-15.docx | Bin 0 -> 45028 bytes .../build_engine_review_docx.py | 367 ++++++++++++++++++ ...~$FINITH_답변엔진_확장검토_2026-09-15.docx | Bin 0 -> 162 bytes supporters/public/favicon.svg | 9 - templates/supporters-astro/public/favicon.svg | 9 - 6 files changed, 368 insertions(+), 18 deletions(-) create mode 100644 docs/reports/answer_engines/INFINITH_답변엔진_확장검토_2026-09-15.docx create mode 100644 docs/reports/answer_engines/build_engine_review_docx.py create mode 100644 docs/reports/answer_engines/~$FINITH_답변엔진_확장검토_2026-09-15.docx delete mode 100644 supporters/public/favicon.svg delete mode 100644 templates/supporters-astro/public/favicon.svg diff --git a/docs/reports/README.md b/docs/reports/README.md index 9bb97f1..d439fed 100644 --- a/docs/reports/README.md +++ b/docs/reports/README.md @@ -12,6 +12,7 @@ docs/reports/ │ └── 05_global_en/ 영문 사이트(viewplasticsurgery.com) 외국인 관점 AEO/GEO 진단 (2026-09-10) · 영문 60문항 뱅크 · Perplexity/OpenAI(뉴욕) 실측 · HTML/PDF 보고서 + 빌더 ├── taeha/ 태하 AI Answer Readiness 리포트 (html · pdf · pptx) + 빌더 ├── ibk/ 기업은행 블로그 AEO/GEO 감사 +├── answer_engines/ 답변엔진 확장 검토 보고서(.docx, 120문항 비용 추정 · 후보별 약관 검토) + 빌더 └── landing/ AI Discovery 랜딩 시안 (픽셀 정답 HTML) · 스크린샷 · 리포트 페이지 HTML 내보내기 스크립트 ``` diff --git a/docs/reports/answer_engines/INFINITH_답변엔진_확장검토_2026-09-15.docx b/docs/reports/answer_engines/INFINITH_답변엔진_확장검토_2026-09-15.docx new file mode 100644 index 0000000000000000000000000000000000000000..00e61b007c3f5291008bfb778665c62a657c388e GIT binary patch literal 45028 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 MgEkMR@?XFH1H06TIsgCw literal 0 HcmV?d00001 diff --git a/docs/reports/answer_engines/build_engine_review_docx.py b/docs/reports/answer_engines/build_engine_review_docx.py new file mode 100644 index 0000000..27346a8 --- /dev/null +++ b/docs/reports/answer_engines/build_engine_review_docx.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python3 +"""답변엔진 확장 검토 보고서(.docx) 빌더. + +질문 뱅크 120문항 기준으로 후보 답변엔진별 비용을 추정하고, 약관 검토 결과와 함께 워드 문서로 낸다. +단가는 2026-09-15 각사 공식 가격표 확인값. 토큰량은 가정이며 4장 표에 근거를 적는다. + +사용: + python3 docs/reports/answer_engines/build_engine_review_docx.py +""" +from pathlib import Path + +from docx import Document +from docx.enum.table import WD_TABLE_ALIGNMENT +from docx.enum.text import WD_ALIGN_PARAGRAPH +from docx.oxml import OxmlElement +from docx.oxml.ns import qn +from docx.shared import Cm, Pt, RGBColor + +OUT = Path(__file__).with_name("INFINITH_답변엔진_확장검토_2026-09-15.docx") + +INDIGO = RGBColor(0x1D, 0x00, 0x24) +VIOLET = RGBColor(0x4F, 0x1D, 0xA1) +GRAY = RGBColor(0x55, 0x55, 0x60) +FONT = "Pretendard" + +KRW = 1345 # 2026-09-13 USD/KRW 1,343.56 기준 반올림 +QUESTIONS = 120 +REPEAT = 5 + +M = 1_000_000 + +# ── 후처리 단가(답변 1건당): 병원명 추출 gpt-4o-mini + 어조 판정 gpt-4.1 ── +def post_cost(level): + rubric_in = {"low": 4000, "mid": 5000, "high": 6000}[level] + answer_in = {"low": 600, "mid": 1000, "high": 2900}[level] + extract = (500 + answer_in) * 0.15 / M + 150 * 0.60 / M + judge = (rubric_in + answer_in) * 2.00 / M + 300 * 8.00 / M + return extract + judge + + +# ── 엔진별 1문항 1회 호출 비용 모델 ── +# searches: 호출당 검색 횟수, search_fee: 검색 1회 단가, tin/tout: 입력·출력 토큰, pin/pout: 1M 토큰 단가 +ENGINES = [ + dict(key="gpt4o", name="ChatGPT (현행)", setup="gpt-4o + web_search", status="운영 중", + search_fee=0.025, pin=2.50, pout=10.00, + low=dict(searches=1, tin=300, tout=400), mid=dict(searches=1, tin=300, tout=1000), high=dict(searches=1, tin=300, tout=2900), + note="비추론 모델은 검색 호출 $25/1천 회, 검색 본문 토큰 무료. 출력은 실측 평균 962자·상위 10% 2,850자."), + dict(key="gpt56", name="ChatGPT (최신화)", setup="GPT-5.6 Sol + web_search", status="모델 교체안", + search_fee=0.010, pin=4.00, pout=20.00, + low=dict(searches=1, tin=8000, tout=1500), mid=dict(searches=2, tin=20000, tout=3000), high=dict(searches=3, tin=40000, tout=5000), + note="추론 모델은 검색 호출 $10/1천 회, 검색 본문 토큰을 모델 단가로 과금. 출력에 추론 토큰 포함."), + dict(key="sonar", name="Perplexity (현행)", setup="sonar, 검색 컨텍스트 low", status="운영 중", + search_fee=0.005, pin=1.00, pout=1.00, + low=dict(searches=1, tin=50, tout=400), mid=dict(searches=1, tin=50, tout=650), high=dict(searches=1, tin=50, tout=1000), + note="요청 수수료 $5/1천 회(low). 출력은 실측 평균 618자."), + dict(key="sonarpro", name="Perplexity (상위)", setup="sonar-pro, 검색 컨텍스트 medium", status="모델 교체안", + search_fee=0.010, pin=3.00, pout=15.00, + low=dict(searches=1, tin=50, tout=700), mid=dict(searches=1, tin=50, tout=1000), high=dict(searches=1, tin=50, tout=1400), + note="요청 수수료 $10/1천 회(medium)."), + dict(key="sonnet5", name="Claude", setup="Claude Sonnet 5 + web_search", status="추가 권고", + search_fee=0.010, pin=2.00, pout=10.00, + low=dict(searches=1, tin=12000, tout=800), mid=dict(searches=2, tin=30000, tout=1500), high=dict(searches=3, tin=60000, tout=3000), + note="검색 $10/1천 회. 검색 결과가 입력 토큰으로 과금되어 입력 토큰이 비용의 대부분."), + dict(key="haiku45", name="Claude (저가)", setup="Claude Haiku 4.5 + web_search", status="대안", + search_fee=0.010, pin=1.00, pout=5.00, + low=dict(searches=1, tin=12000, tout=800), mid=dict(searches=2, tin=30000, tout=1500), high=dict(searches=3, tin=60000, tout=3000), + note="Sonnet 5와 같은 토큰량 가정. 동적 필터링(입력 절감)은 4.6 이상 모델만 지원."), + dict(key="gemini", name="Gemini", setup="Gemini 3.8 Flash + Google 검색 그라운딩", status="약관 확인 전 보류", + search_fee=0.0, pin=0.75, pout=3.75, + low=dict(searches=1, tin=300, tout=1000), mid=dict(searches=2, tin=300, tout=2000), high=dict(searches=3, tin=300, tout=4000), + note="그라운딩 월 5,000회 무료(3.x 공통), 초과 시 $14/1천 회. 120문항 5회 반복은 최대 1,800회라 무료 범위 안."), + dict(key="grok", name="Grok", setup="Grok 4.3 + web search", status="후순위", + search_fee=0.005, pin=1.25, pout=2.50, + low=dict(searches=1, tin=8000, tout=800), mid=dict(searches=2, tin=20000, tout=1500), high=dict(searches=3, tin=40000, tout=3000), + note="검색 $5/1천 회는 제3자 정리 기준. 공식 가격표 재확인 필요."), + dict(key="bing", name="Copilot 계열", setup="Azure Foundry + Grounding with Bing + gpt-4o", status="제외 (약관)", + search_fee=0.014, pin=2.50, pout=10.00, + low=dict(searches=1, tin=5000, tout=400), mid=dict(searches=1, tin=10000, tout=1000), high=dict(searches=2, tin=20000, tout=2900), + note="참고용 산정. 결과 저장·데이터베이스화 금지 조항으로 측정에 쓸 수 없음."), + dict(key="aio", name="Google AI Mode", setup="DataForSEO AI Mode SERP API", status="결정 필요", + search_fee=0.004, pin=0.0, pout=0.0, + low=dict(searches=1, tin=0, tout=0), mid=dict(searches=1, tin=0, tout=0), high=dict(searches=1, tin=0, tout=0), + note="Live $0.004, Standard 대기열 $0.0012 / 요청. 모델 토큰 없음. 소비자 화면을 제3자가 수집하는 방식."), +] + + +def call_cost(e, level): + p = e[level] + return p["searches"] * e["search_fee"] + p["tin"] * e["pin"] / M + p["tout"] * e["pout"] / M + + +def per_question(e, level, with_post=True): + return call_cost(e, level) + (post_cost(level) if with_post else 0) + + +def usd(x): + return f"${x:,.2f}" if x >= 0.995 else f"${x:.3f}" + + +def won(x): + return f"₩{round(x * KRW, -1):,.0f}" + + +# ── 문서 헬퍼 ── +def set_font(run, size=11, bold=False, color=INDIGO): + run.font.name = FONT + run.font.size = Pt(size) + run.font.bold = bold + run.font.color.rgb = color + rpr = run._element.get_or_add_rPr() + rfonts = rpr.find(qn("w:rFonts")) + if rfonts is None: + rfonts = OxmlElement("w:rFonts") + rpr.append(rfonts) + for attr in ("w:ascii", "w:hAnsi", "w:cs", "w:eastAsia"): + rfonts.set(qn(attr), FONT) + + +def para(doc, text, size=11, bold=False, color=INDIGO, space_after=6, align=None): + p = doc.add_paragraph() + p.paragraph_format.space_after = Pt(space_after) + p.paragraph_format.line_spacing = 1.35 + if align: + p.alignment = align + set_font(p.add_run(text), size, bold, color) + return p + + +def heading(doc, text, level=1): + size = {0: 24, 1: 16, 2: 13}[level] + p = doc.add_paragraph() + p.paragraph_format.space_before = Pt(18 if level == 1 else 10) + p.paragraph_format.space_after = Pt(8) + p.paragraph_format.keep_with_next = True + set_font(p.add_run(text), size, True, INDIGO if level != 2 else VIOLET) + return p + + +def bullets(doc, items, size=11): + for t in items: + p = doc.add_paragraph(style="List Bullet") + p.paragraph_format.space_after = Pt(3) + p.paragraph_format.line_spacing = 1.3 + if isinstance(t, tuple): + set_font(p.add_run(t[0]), size, True) + set_font(p.add_run(t[1]), size) + else: + set_font(p.add_run(t), size) + + +def shade(cell, hex_fill): + tcpr = cell._element.get_or_add_tcPr() + shd = OxmlElement("w:shd") + shd.set(qn("w:val"), "clear") + shd.set(qn("w:color"), "auto") + shd.set(qn("w:fill"), hex_fill) + tcpr.append(shd) + + +def table(doc, header, rows, widths=None, size=9.5, bold_first_col=True, highlight_rows=()): + t = doc.add_table(rows=1, cols=len(header)) + t.style = "Table Grid" + t.alignment = WD_TABLE_ALIGNMENT.CENTER + for i, h in enumerate(header): + c = t.rows[0].cells[i] + c.text = "" + set_font(c.paragraphs[0].add_run(h), size, True, RGBColor(0xFF, 0xFF, 0xFF)) + shade(c, "1D0024") + trpr = t.rows[0]._tr.get_or_add_trPr() + for tag in ("w:tblHeader", "w:cantSplit"): + el = OxmlElement(tag) + el.set(qn("w:val"), "true") + trpr.append(el) + for ri, r in enumerate(rows): + cells = t.add_row().cells + for i, v in enumerate(r): + cells[i].text = "" + bold = (i == 0 and bold_first_col) or ri in highlight_rows + set_font(cells[i].paragraphs[0].add_run(str(v)), size, bold) + if ri in highlight_rows: + shade(cells[i], "F1ECFA") + if widths: + t.autofit = False + for i, w in enumerate(widths): + t.columns[i].width = Cm(w) + for row in t.rows: + for i, w in enumerate(widths): + row.cells[i].width = Cm(w) + doc.add_paragraph().paragraph_format.space_after = Pt(2) + return t + + +def build(): + E = {e["key"]: e for e in ENGINES} + doc = Document() + sec = doc.sections[0] + sec.page_width, sec.page_height = Cm(21.0), Cm(29.7) + sec.left_margin = sec.right_margin = Cm(2.0) + sec.top_margin = sec.bottom_margin = Cm(2.0) + + # 표지 블록 + para(doc, "INFINITH AI Discovery", 11, True, VIOLET, 4) + heading(doc, "답변엔진 확장 검토 보고서", 0) + para(doc, "질문 뱅크 120문항 기준 비용 추정과 후보 엔진별 약관 검토", 13, False, INDIGO, 4) + para(doc, "작성일 2026-09-15 · 단가 확인일 2026-09-15 · 환율 1 USD = ₩1,345 가정", 10, False, GRAY, 14) + + # 1. 요약 + heading(doc, "1. 요약") + gpt4o, sonar, sonnet, gem = E["gpt4o"], E["sonar"], E["sonnet5"], E["gemini"] + cur_q = per_question(gpt4o, "mid") + per_question(sonar, "mid") + add_claude_q = per_question(sonnet, "mid") + bullets(doc, [ + ("현재 실측 엔진은 2개입니다. ", "ChatGPT(gpt-4o + 웹 검색)와 Perplexity(sonar)입니다. 36개 진단 항목은 AI 모델 없이 규칙 검사로 판정합니다."), + ("바로 추가할 수 있는 엔진은 Claude입니다. ", "공식 API에 웹 검색 도구가 있고, 결과 저장·분석을 막는 조항을 확인하지 못했습니다."), + ("Gemini와 Copilot은 약관이 측정 용도와 충돌합니다. ", "Gemini는 그라운딩 결과의 분석·자동 수집을, Bing 그라운딩은 결과 저장·데이터베이스화를 금지합니다."), + ("비용은 크지 않습니다. ", + f"현행 2개 엔진의 120문항 1회 측정은 약 {usd(cur_q * QUESTIONS)}({won(cur_q * QUESTIONS)})이고, " + f"Claude를 더하면 1회 약 {usd(add_claude_q * QUESTIONS)}({won(add_claude_q * QUESTIONS)})가 늘어납니다. 모두 중앙 추정치이며 후처리(병원명 추출·어조 판정) 비용을 포함합니다."), + ("네이버 AI 브리핑은 측정 API가 없습니다. ", "수동 스팟체크를 유지합니다."), + ]) + + # 2. 현재 구성 + heading(doc, "2. 현재 측정 구성") + table(doc, ["역할", "모델 · 방식", "코드 위치"], [ + ["답변엔진 실측 ①", "OpenAI gpt-4o + Responses API web_search (서울 고정, 영문판 뉴욕)", "scripts/run_question_bank_openai.py"], + ["답변엔진 실측 ②", "Perplexity sonar (웹 검색 내장)", "scripts/run_question_bank_openai.py"], + ["병원명·순위 추출", "OpenAI gpt-4o-mini (키 없으면 Gemini 2.5 Flash)", "scripts/run_question_bank_openai.py"], + ["어조 판정", "OpenAI gpt-4.1, temperature 0", "scripts/sentiment_qb.py"], + ["36개 항목 진단", "AI 모델 미사용. 크롤링 규칙 검사 + Wikidata 조회", "scripts/audit_aeo_geo.py"], + ], widths=[3.2, 8.6, 5.2]) + para(doc, "측정은 공식 API 답변 기준입니다. 소비자 화면(chatgpt.com 등) 자동 조회는 약관상 하지 않으므로, API 답변과 화면 답변은 다를 수 있습니다.", 10, False, GRAY) + + # 3. 후보별 검토 + heading(doc, "3. 후보 엔진별 검토") + table(doc, ["엔진", "공식 API", "약관상 측정 가능 여부", "판정"], [ + ["Claude", "Messages API web_search 도구. user_location으로 도시·국가 지정", "저장·분석 금지 조항 미확인. 최종 사용자에게 보여줄 때 출처 표시 필요", "추가 권고"], + ["Gemini", "Grounding with Google Search. GEMINI_API_KEY 보유", "그라운딩 결과의 cache·analyze·자동 수집 금지. 질문한 사용자에게 보여주는 용도만 허용", "법무 확인 전 보류"], + ["Copilot 계열", "Azure Foundry Grounding with Bing Search", "결과의 store·cache·archive·데이터베이스화 금지. 검색 경험 앱에서만 사용", "제외"], + ["Grok", "xAI API web search 도구", "저장 금지 조항 별도 확인 안 함", "후순위 (국내 이용 비중 낮음)"], + ["Google AI Overview · AI Mode", "Google 공식 API 없음. DataForSEO·SerpApi가 결과 화면을 수집해 제공", "제3자가 소비자 화면을 수집하는 방식. 현재 수집 원칙과 불일치", "haewon 결정 필요"], + ["네이버 AI 브리핑", "없음. CLOVA Studio는 모델 API이며 브리핑 화면을 재현하지 못함", "해당 없음", "제외, 수동 스팟체크"], + ["DeepSeek · 뤼튼 · 라이너", "웹 검색이 붙은 공식 측정 API 미확인", "해당 없음", "제외"], + ], widths=[3.0, 5.2, 6.0, 2.8]) + + heading(doc, "3.1 엔진별 판단 근거", 2) + bullets(doc, [ + ("Claude. ", "검색 1,000회당 $10에 검색 결과가 입력 토큰으로 과금됩니다. 응답에 인용 URL과 인용 문장(최대 150자)이 구조화되어 와서 현재 추출 로직에 붙이기 쉽습니다. 국내 병원 고객의 이용 비중은 ChatGPT보다 낮습니다."), + ("Gemini. ", "기술 난이도는 가장 낮고 국내 비중은 Claude보다 높습니다. 다만 Gemini API 추가 약관이 Grounded Results를 \"cache, frame, syndicate, resell, analyze\" 하는 것을 금지하고, 자동 수집을 허용하지 않습니다. Vertex AI 경로의 약관이 다른지와, 진단을 요청한 고객에게 결과를 보여주는 용도로 인정되는지 법무 판단이 필요합니다."), + ("Copilot 계열. ", "Bing 그라운딩 약관이 결과를 \"Copy, store, cache, archive, or create a database of Output\" 하는 것을 금지합니다. 질문 뱅크 결과를 누적하는 방식과 양립하지 않습니다."), + ("Google AI Overview · AI Mode. ", "병원 검색에서 노출 비중이 큰 화면이고 비용도 가장 낮습니다. 대신 Google 검색 결과를 제3자 도구로 수집하는 구조라, \"소비자 화면을 자동 조회하지 않는다\"는 현재 원칙을 바꾸는 결정입니다."), + ("기존 엔진 모델 점검. ", "ChatGPT 소비자 화면은 gpt-4o보다 새 모델로 답합니다. 측정 모델을 최신 추론 모델로 바꾸면 화면 답변과의 차이가 줄지만, 문항당 비용이 약 3.5배 늘어납니다(5장 표)."), + ]) + + # 4. 비용 산정 기준 + heading(doc, "4. 비용 산정 기준") + table(doc, ["항목", "가정", "근거"], [ + ["문항 수", "120문항", "질문 뱅크 v0.1"], + ["반복", "1회, 5회 반복 두 가지", "답변 변동을 신뢰구간으로 보고하려면 5~7회 반복 필요"], + ["답변 길이", "ChatGPT 평균 962자(상위 10% 2,850자), Perplexity 평균 618자", "scripts/out 실측 결과 240건"], + ["한국어 토큰 환산", "1자 ≈ 1토큰 (보수적)", "모델별 토크나이저 차이는 범위(최소·최대)로 흡수"], + ["검색 결과 입력 토큰", "Claude 1.2만~6만, OpenAI 추론 모델 0.8만~4만, Grok 0.8만~4만", "검색 1~3회 × 결과 본문. 실측 전 가정"], + ["후처리", f"답변 1건당 약 {usd(post_cost('mid'))}", "gpt-4o-mini 추출 + gpt-4.1 어조 판정(기준표 프롬프트 약 5천 토큰)"], + ["환율", "1 USD = ₩1,345", "2026-09-13 USD/KRW 1,343.56"], + ["할인", "미적용", "Batch API 50% 할인은 적용 시 토큰 비용만 절감"], + ], widths=[3.2, 7.3, 6.5]) + + # 5. 엔진별 비용 + heading(doc, "5. 120문항 비용 추정 (엔진별)") + para(doc, "문항당 단가는 엔진 호출 1회와 후처리 1건을 합한 값입니다. 범위는 최소·최대 가정, 굵은 값은 중앙 추정입니다.", 10, False, GRAY) + rows = [] + for e in ENGINES: + lo, mid, hi = (per_question(e, lv) for lv in ("low", "mid", "high")) + rows.append([ + e["name"], e["setup"], e["status"], usd(mid), + f"{usd(mid * QUESTIONS)}\n{won(mid * QUESTIONS)}", + f"{usd(mid * QUESTIONS * REPEAT)}\n{won(mid * QUESTIONS * REPEAT)}", + f"{usd(lo * QUESTIONS * REPEAT)} ~ {usd(hi * QUESTIONS * REPEAT)}", + ]) + table(doc, ["엔진", "구성", "상태", "문항당", "120문항 1회", "120문항 5회", "5회 범위"], rows, + widths=[2.4, 3.9, 2.2, 1.6, 2.3, 2.3, 2.6], size=9, highlight_rows=(0, 2, 4)) + bullets(doc, [ + "Gemini 행은 그라운딩 무료 범위(월 5,000회) 안에서 계산했습니다. 무료 범위를 넘으면 검색 1,000회당 $14가 더해져 5회 반복 기준 최대 " + f"{usd(1800 * 0.014)}가 늘어납니다.", + "Copilot 계열은 약관상 사용할 수 없어 참고용으로만 적었습니다.", + "Google AI Mode는 모델 호출이 없어 비용 대부분이 후처리입니다. Standard 대기열($0.0012)을 쓰면 수집 비용이 70% 줄어듭니다.", + ], size=10) + heading(doc, "5.1 엔진별 산정 메모", 2) + table(doc, ["엔진", "과금 구조"], [[e["name"], e["note"]] for e in ENGINES], widths=[3.2, 13.8], size=9) + + # 6. 구성안 + heading(doc, "6. 구성안별 합계") + plans = [ + ("A. 현행 유지", ["gpt4o", "sonar"], "현재 운영 구성"), + ("B. 현행 + Claude", ["gpt4o", "sonar", "sonnet5"], "권고안. 랜딩에 ChatGPT·Perplexity·Claude 표기 가능"), + ("C. 모델 최신화 + Claude", ["gpt56", "sonarpro", "sonnet5"], "소비자 화면과의 차이를 줄이는 안"), + ("D. B + Gemini", ["gpt4o", "sonar", "sonnet5", "gemini"], "Gemini 약관 확인이 끝난 경우"), + ("E. D + Google AI Mode", ["gpt4o", "sonar", "sonnet5", "gemini", "aio"], "수집 원칙 변경을 결정한 경우"), + ] + prow = [] + for name, keys, desc in plans: + lo = sum(per_question(E[k], "low") for k in keys) + mid = sum(per_question(E[k], "mid") for k in keys) + hi = sum(per_question(E[k], "high") for k in keys) + prow.append([name, f"{len(keys)}개", desc, + f"{usd(mid * QUESTIONS)}\n{won(mid * QUESTIONS)}", + f"{usd(mid * QUESTIONS * REPEAT)}\n{won(mid * QUESTIONS * REPEAT)}", + f"{won(lo * QUESTIONS * REPEAT)} ~ {won(hi * QUESTIONS * REPEAT)}"]) + table(doc, ["구성안", "엔진", "설명", "120문항 1회", "120문항 5회", "5회 범위(원)"], prow, + widths=[3.2, 1.3, 4.8, 2.5, 2.5, 3.0], size=9, highlight_rows=(1,)) + para(doc, "병원 1곳을 월 1회, 5회 반복으로 측정하면 월 비용은 \"120문항 5회\" 열과 같습니다. 병원 수에 비례해 늘어납니다.", 10, False, GRAY) + + # 7. 권고 + heading(doc, "7. 권고와 결정 필요 사항") + heading(doc, "7.1 권고 순서", 2) + bullets(doc, [ + ("1단계. Claude 엔진 추가 (구성안 B). ", "run_question_bank_openai.py에 엔진 클래스를 하나 추가합니다. 10문항 시험 실행으로 실제 토큰량을 확인한 뒤 120문항을 돌립니다."), + ("2단계. 기존 엔진 모델 점검. ", "10문항을 gpt-4o와 최신 추론 모델로 나란히 돌려 병원 언급률 차이를 봅니다. 차이가 크면 구성안 C로 올립니다."), + ("3단계. Gemini 약관 확인. ", "Vertex AI 약관과 AI Studio 약관을 비교하고 법무 판단을 받습니다."), + ("4단계. Google AI Mode 수집 여부 결정. ", "수집 원칙 변경이 필요합니다."), + ]) + heading(doc, "7.2 haewon 결정 필요", 2) + table(doc, ["번호", "결정 사항", "선택지"], [ + ["1", "Claude 엔진 추가와 10문항 시험 실행", "진행 / 보류"], + ["2", "측정 모델 최신화 시험 (gpt-4o 대비 최신 모델)", "진행 / 보류"], + ["3", "Gemini 약관 법무 검토 요청", "요청 / 보류"], + ["4", "Google AI Overview · AI Mode 제3자 수집 허용", "허용 / 불허"], + ["5", "Anthropic API 회사 키 발급", "발급 / 기존 키 사용"], + ], widths=[1.4, 10.0, 5.6]) + + # 8. 한계 + heading(doc, "8. 이 추정의 한계") + bullets(doc, [ + "검색 결과 입력 토큰은 실측 전 가정입니다. Claude·OpenAI 추론 모델·Grok 비용은 이 값에 따라 2배 안팎 달라질 수 있습니다. 10문항 시험 실행 후 5장 표를 갱신합니다.", + "Grok 검색 단가는 제3자 정리 기준이고, 약관 조항은 요약본을 읽은 것입니다. 도입 판단 전에 원문을 다시 확인해야 합니다.", + "Gemini 3.x Flash 할인 단가는 2026-12-31까지이며, 2027-01-01부터 입력·출력 단가가 2배로 오릅니다.", + "API 답변은 각 서비스의 소비자 앱 답변과 같지 않습니다. 엔진을 늘려도 보고서에는 \"공식 API 답변 기준\"으로 표기해야 합니다.", + "환율 변동과 부가세는 반영하지 않았습니다.", + ], size=10) + + # 9. 출처 + heading(doc, "9. 출처 (2026-09-15 확인)") + for label, url in [ + ("OpenAI API Pricing", "https://developers.openai.com/api/docs/pricing"), + ("Perplexity Sonar Pricing", "https://docs.perplexity.ai/getting-started/pricing"), + ("Claude Pricing", "https://platform.claude.com/docs/en/about-claude/pricing"), + ("Claude Web search tool", "https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool"), + ("Gemini API Pricing", "https://ai.google.dev/gemini-api/docs/pricing"), + ("Gemini API Additional Terms", "https://ai.google.dev/gemini-api/terms"), + ("Grounding with Bing pricing", "https://www.microsoft.com/en-us/bing/apis/grounding-pricing"), + ("Grounding with Bing legal", "https://www.microsoft.com/en-us/bing/apis/grounding-legal"), + ("xAI models", "https://docs.x.ai/docs/models"), + ("xAI Grok API pricing (제3자 정리)", "https://mem0.ai/blog/xai-grok-api-pricing"), + ("DataForSEO Google AI Mode SERP API", "https://dataforseo.com/pricing/google-serp/google-ai-mode-serp-api"), + ("CLOVA Studio API 가이드", "https://api.ncloud-docs.com/docs/ai-naver-clovastudio-summary"), + ("원·달러 환율 (2026-09-13)", "https://ko.tradingeconomics.com/south-korea/currency"), + ]: + p = doc.add_paragraph() + p.paragraph_format.space_after = Pt(2) + set_font(p.add_run(f"{label} "), 9.5, True) + set_font(p.add_run(url), 9.5, False, GRAY) + + doc.save(OUT) + print(OUT) + + +if __name__ == "__main__": + build() diff --git a/docs/reports/answer_engines/~$FINITH_답변엔진_확장검토_2026-09-15.docx b/docs/reports/answer_engines/~$FINITH_답변엔진_확장검토_2026-09-15.docx new file mode 100644 index 0000000000000000000000000000000000000000..fd5ab39b543fabd30160a01b64853b3a8aa89fea GIT binary patch literal 162 ucmd<`NK7ry&r|SD%w-@Ra4~o=Br>Ejlr!Wr - - - diff --git a/templates/supporters-astro/public/favicon.svg b/templates/supporters-astro/public/favicon.svg deleted file mode 100644 index f157bd1..0000000 --- a/templates/supporters-astro/public/favicon.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - -