from __future__ import annotations from dataclasses import dataclass from pathlib import Path from typing import Iterable, Sequence from pptx import Presentation from pptx.dml.color import RGBColor from pptx.enum.shapes import MSO_AUTO_SHAPE_TYPE from pptx.enum.text import PP_ALIGN from pptx.util import Inches, Pt @dataclass(frozen=True) class Theme: navy: RGBColor navy_2: RGBColor bg: RGBColor white: RGBColor text: RGBColor muted: RGBColor line: RGBColor accent_yellow: RGBColor accent_blue: RGBColor accent_red: RGBColor accent_green: RGBColor font: str font_bold: str T = Theme( navy=RGBColor(0x10, 0x1D, 0x2E), navy_2=RGBColor(0x14, 0x2A, 0x45), bg=RGBColor(0xF6, 0xF7, 0xFB), white=RGBColor(0xFF, 0xFF, 0xFF), text=RGBColor(0x1F, 0x29, 0x37), muted=RGBColor(0x6B, 0x72, 0x80), line=RGBColor(0xE5, 0xE7, 0xEB), accent_yellow=RGBColor(0xF0, 0xB4, 0x3B), accent_blue=RGBColor(0x3B, 0x82, 0xF6), accent_red=RGBColor(0xEF, 0x44, 0x44), accent_green=RGBColor(0x22, 0xC5, 0x5E), font="Apple SD Gothic Neo", font_bold="Apple SD Gothic Neo", ) SLIDE_W = Inches(13.333) SLIDE_H = Inches(7.5) def _rgb(hex6: str) -> RGBColor: h = hex6.lstrip("#") return RGBColor(int(h[0:2], 16), int(h[2:4], 16), int(h[4:6], 16)) def set_slide_bg(slide, color: RGBColor) -> None: fill = slide.background.fill fill.solid() fill.fore_color.rgb = color def add_rect(slide, x, y, w, h, *, fill: RGBColor | None, line: RGBColor | None, radius: bool = False): shape_type = MSO_AUTO_SHAPE_TYPE.ROUNDED_RECTANGLE if radius else MSO_AUTO_SHAPE_TYPE.RECTANGLE shp = slide.shapes.add_shape(shape_type, x, y, w, h) if fill is None: shp.fill.background() else: shp.fill.solid() shp.fill.fore_color.rgb = fill if line is None: shp.line.fill.background() else: shp.line.color.rgb = line shp.line.width = Pt(1) return shp def add_textbox( slide, x, y, w, h, text: str, *, size: int, bold: bool = False, color: RGBColor | None = None, align: int = PP_ALIGN.LEFT, line_spacing: float | None = None, ): tb = slide.shapes.add_textbox(x, y, w, h) tf = tb.text_frame tf.clear() p = tf.paragraphs[0] run = p.add_run() run.text = text f = run.font f.name = T.font_bold if bold else T.font f.size = Pt(size) f.bold = bold f.color.rgb = color or T.text p.alignment = align if line_spacing is not None: p.line_spacing = line_spacing return tb def add_bullets( slide, x, y, w, h, bullets: Sequence[str], *, size: int = 18, color: RGBColor | None = None, bullet_color: RGBColor | None = None, line_spacing: float = 1.15, ): tb = slide.shapes.add_textbox(x, y, w, h) tf = tb.text_frame tf.clear() tf.word_wrap = True for i, b in enumerate(bullets): p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() p.text = b p.level = 0 p.font.name = T.font p.font.size = Pt(size) p.font.color.rgb = color or T.text p.line_spacing = line_spacing p.space_after = Pt(6) p.bullet = True if bullet_color is not None: # python-pptx doesn't support bullet color directly; keep as text color. pass return tb def add_pill(slide, x, y, w, h, text: str, *, fill: RGBColor, fg: RGBColor): pill = add_rect(slide, x, y, w, h, fill=fill, line=None, radius=True) tf = pill.text_frame tf.clear() p = tf.paragraphs[0] p.alignment = PP_ALIGN.CENTER run = p.add_run() run.text = text run.font.name = T.font run.font.size = Pt(12) run.font.color.rgb = fg return pill def add_footer(slide, slide_no: int, *, dark: bool) -> None: y = SLIDE_H - Inches(0.35) add_rect(slide, Inches(0), y, SLIDE_W, Inches(0.35), fill=(T.navy if dark else T.bg), line=None, radius=False) fg = _rgb("#D1D5DB") if dark else T.muted add_textbox( slide, Inches(0.5), y + Inches(0.06), Inches(6), Inches(0.25), "윤도상 | 2026.03", size=11, bold=False, color=fg, align=PP_ALIGN.LEFT, ) add_textbox( slide, SLIDE_W - Inches(2.0), y + Inches(0.06), Inches(1.5), Inches(0.25), f"Slide {slide_no:02d}" if dark else f"{slide_no:02d}", size=11, bold=False, color=fg, align=PP_ALIGN.RIGHT, ) def add_title_block( slide, title: str, subtitle: str | None = None, *, dark: bool, y: float = 0.6, pretitle: str | None = None, ): fg = T.white if dark else T.text if pretitle: add_textbox( slide, Inches(0.7), Inches(y), Inches(12), Inches(0.3), pretitle, size=14, bold=True, color=T.accent_yellow if dark else T.accent_yellow, ) y += 0.35 add_textbox( slide, Inches(0.7), Inches(y), Inches(12), Inches(0.8), title, size=40 if len(title) <= 18 else 34, bold=True, color=fg, ) if subtitle: add_textbox( slide, Inches(0.7), Inches(y + 0.85), Inches(12), Inches(0.4), subtitle, size=18, bold=True, color=T.accent_yellow if dark else T.muted, ) def add_card( slide, x, y, w, h, *, title: str, body: Sequence[str], accent: RGBColor, dark_text: bool = True, ): add_rect(slide, x, y, w, h, fill=T.white, line=T.line, radius=True) add_rect(slide, x, y, w, Inches(0.08), fill=accent, line=None, radius=False) add_textbox( slide, x + Inches(0.25), y + Inches(0.4), w - Inches(0.5), Inches(0.4), title, size=18, bold=True, color=T.text if dark_text else T.white, ) add_bullets( slide, x + Inches(0.25), y + Inches(0.9), w - Inches(0.5), h - Inches(1.1), list(body), size=14, color=T.muted, line_spacing=1.2, ) def slide_01_cover(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.navy) add_pill( s, Inches(4.2), Inches(0.35), Inches(4.9), Inches(0.42), "LLM AI 툴 활용 교육", fill=_rgb("#24364D"), fg=_rgb("#E5E7EB"), ) add_textbox(s, Inches(3.6), Inches(2.1), Inches(6.2), Inches(0.9), "AI에게", size=54, bold=True, color=T.white, align=PP_ALIGN.CENTER) add_textbox(s, Inches(2.9), Inches(3.05), Inches(7.6), Inches(0.9), "잘 시키는 법", size=54, bold=True, color=T.white, align=PP_ALIGN.CENTER) add_rect(s, Inches(6.1), Inches(4.1), Inches(1.2), Inches(0.05), fill=T.accent_yellow, line=None) add_textbox( s, Inches(2.4), Inches(4.35), Inches(8.6), Inches(0.5), "실무자를 위한 LLM 프롬프트 & 워크플로우 완전 가이드", size=18, bold=True, color=T.accent_yellow, align=PP_ALIGN.CENTER, ) add_footer(s, 1, dark=True) def slide_02_core_assumptions(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "AI 활용의 핵심 전제 3가지", size=14, bold=True, color=T.accent_yellow) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "이것만 알아도 80%다", size=40, bold=True, color=T.text) add_pill(s, Inches(10.1), Inches(1.1), Inches(2.6), Inches(0.38), "Chapter 1. AI는 어떻게 생각하는가?", fill=_rgb("#EEF2F7"), fg=T.muted) cw = Inches(3.95) ch = Inches(2.7) y = Inches(2.05) gap = Inches(0.4) x1 = Inches(0.7) add_card( s, x1, y, cw, ch, title="AI는 당신이 준\n정보만큼 답한다", body=["입력(Prompt)의 질이 곧", "출력(Output)의 질을 결정합니다.", "맥락이 없으면 답도 없습니다."], accent=T.accent_blue, ) add_card( s, x1 + cw + gap, y, cw, ch, title="AI는 틀린 답을\n자신 있게 말한다", body=["환각(Hallucination) 현상은", "AI의 구조적 특성입니다.", "절대 맹신하지 마세요."], accent=T.accent_red, ) add_card( s, x1 + (cw + gap) * 2, y, cw, ch, title="AI는 도구이지,\n판단자가 아니다", body=["결과물에 대한 최종 검증과", "책임은 항상 사람(나)에게", "있습니다."], accent=T.accent_green, ) bar_y = Inches(5.55) add_rect(s, Inches(0.7), bar_y, Inches(11.93), Inches(0.85), fill=T.navy_2, line=None, radius=True) add_pill(s, Inches(0.95), bar_y + Inches(0.18), Inches(1.15), Inches(0.42), "실제 사례", fill=T.accent_yellow, fg=T.navy) add_pill(s, Inches(2.2), bar_y + Inches(0.18), Inches(3.1), Inches(0.42), "\"세차장에 갑니다\" (중의적)", fill=_rgb("#2B3E59"), fg=_rgb("#E5E7EB")) add_textbox(s, Inches(5.35), bar_y + Inches(0.18), Inches(0.4), Inches(0.42), "→", size=22, bold=True, color=T.accent_yellow, align=PP_ALIGN.CENTER) add_pill(s, Inches(5.7), bar_y + Inches(0.18), Inches(3.2), Inches(0.42), "\"세차하러 갑니다\" (명확)", fill=_rgb("#2B3E59"), fg=_rgb("#E5E7EB")) add_textbox( s, Inches(9.1), bar_y + Inches(0.18), Inches(3.3), Inches(0.42), "정보 단 하나(목적) 차이로\nAI의 답변 품질이 완전히 달라집니다!", size=12, bold=True, color=_rgb("#E5E7EB"), align=PP_ALIGN.RIGHT, ) add_footer(s, 2, dark=False) def slide_03_llm(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.navy) add_title_block(s, "LLM이란 무엇인가?", "Large Language Model — 대규모 언어 모델", dark=True, y=0.5) add_pill(s, Inches(11.5), Inches(0.6), Inches(1.4), Inches(0.38), "Chapter 1", fill=_rgb("#24364D"), fg=_rgb("#E5E7EB")) x = Inches(0.7) y = Inches(2.0) w = Inches(4.8) h = Inches(1.05) gap = Inches(0.35) def left_item(yy, title, desc): add_rect(s, x, yy, w, h, fill=_rgb("#1B2A3F"), line=_rgb("#2B3E59"), radius=True) add_textbox(s, x + Inches(0.3), yy + Inches(0.2), w - Inches(0.6), Inches(0.35), title, size=18, bold=True, color=T.white) add_textbox(s, x + Inches(0.3), yy + Inches(0.55), w - Inches(0.6), Inches(0.45), desc, size=13, bold=False, color=_rgb("#D1D5DB")) left_item(y, "확률 기반 언어 예측", "다음에 올 단어를 통계적으로\n예측하는 '확률 기계'입니다.") left_item(y + h + gap, "\"지식\"이 아닌 \"패턴\"", "사전처럼 정답을 저장한 것이 아니라,\n수많은 문장의 패턴을 학습했습니다.") left_item(y + (h + gap) * 2, "확률적 답변 생성", "같은 질문에도 매번 확률적으로\n가장 자연스러운 답을 생성합니다.") # Right diagram card rx = Inches(5.8) ry = Inches(2.05) rw = Inches(7.0) rh = Inches(4.25) add_rect(s, rx, ry, rw, rh, fill=_rgb("#1B2A3F"), line=_rgb("#2B3E59"), radius=True) add_textbox(s, rx + Inches(0.35), ry + Inches(0.25), Inches(4), Inches(0.35), "LLM 작동 프로세스 예시", size=13, bold=True, color=_rgb("#9CA3AF")) # INPUT box add_textbox(s, rx + Inches(0.55), ry + Inches(0.8), Inches(1.5), Inches(0.3), "INPUT (입력)", size=11, bold=True, color=_rgb("#9CA3AF")) add_rect(s, rx + Inches(0.55), ry + Inches(1.15), Inches(2.2), Inches(0.85), fill=_rgb("#132236"), line=_rgb("#2B3E59"), radius=True) add_textbox( s, rx + Inches(0.7), ry + Inches(1.28), Inches(1.9), Inches(0.55), "\"대한민국의\n수도는\"", size=16, bold=True, color=T.white, align=PP_ALIGN.CENTER, ) # Prediction circle add_textbox(s, rx + Inches(3.0), ry + Inches(0.8), Inches(2.5), Inches(0.3), "PREDICTION (예측)", size=11, bold=True, color=T.accent_yellow, align=PP_ALIGN.CENTER) circ = s.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.OVAL, rx + Inches(3.2), ry + Inches(1.05), Inches(2.55), Inches(2.55)) circ.fill.background() circ.line.color.rgb = T.accent_yellow circ.line.width = Pt(2) # Prob bars inside add_textbox(s, rx + Inches(3.35), ry + Inches(1.45), Inches(2.25), Inches(0.25), "서울 92%", size=11, bold=True, color=_rgb("#E5E7EB")) add_rect(s, rx + Inches(3.35), ry + Inches(1.72), Inches(2.1), Inches(0.08), fill=T.accent_yellow, line=None) add_textbox(s, rx + Inches(3.35), ry + Inches(1.95), Inches(2.25), Inches(0.25), "부산 5%", size=11, bold=False, color=_rgb("#9CA3AF")) add_rect(s, rx + Inches(3.35), ry + Inches(2.22), Inches(0.55), Inches(0.08), fill=_rgb("#64748B"), line=None) add_textbox(s, rx + Inches(3.35), ry + Inches(2.45), Inches(2.25), Inches(0.25), "평양 1%", size=11, bold=False, color=_rgb("#9CA3AF")) add_rect(s, rx + Inches(3.35), ry + Inches(2.72), Inches(0.25), Inches(0.08), fill=_rgb("#64748B"), line=None) # OUTPUT box add_textbox(s, rx + Inches(5.85), ry + Inches(0.8), Inches(1.5), Inches(0.3), "OUTPUT (출력)", size=11, bold=True, color=_rgb("#9CA3AF"), align=PP_ALIGN.RIGHT) add_rect(s, rx + Inches(5.6), ry + Inches(1.25), Inches(2.15), Inches(0.85), fill=_rgb("#0F2C2A"), line=_rgb("#34D399"), radius=True) add_textbox( s, rx + Inches(5.75), ry + Inches(1.38), Inches(1.85), Inches(0.55), "\"서울입니다.\"", size=18, bold=True, color=_rgb("#A7F3D0"), align=PP_ALIGN.CENTER, ) # Arrows add_textbox(s, rx + Inches(2.85), ry + Inches(1.45), Inches(0.3), Inches(0.3), "›", size=28, bold=True, color=_rgb("#9CA3AF"), align=PP_ALIGN.CENTER) add_textbox(s, rx + Inches(5.45), ry + Inches(1.45), Inches(0.3), Inches(0.3), "›", size=28, bold=True, color=_rgb("#9CA3AF"), align=PP_ALIGN.CENTER) add_rect(s, rx + Inches(0.45), ry + Inches(3.8), rw - Inches(0.9), Inches(0.55), fill=_rgb("#24364D"), line=None, radius=True) add_textbox( s, rx + Inches(0.7), ry + Inches(3.92), rw - Inches(1.4), Inches(0.3), "ChatGPT, Claude, Gemini 등은 모두 이와 같은 원리로 작동합니다.", size=12, bold=True, color=_rgb("#D1D5DB"), align=PP_ALIGN.CENTER, ) add_footer(s, 3, dark=True) def slide_04_good_vs_bad(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "효율적인 AI 활용을 위한 첫걸음", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AI가 잘하는 것 vs 못하는 것", size=40, bold=True, color=T.text) add_pill(s, Inches(9.9), Inches(1.1), Inches(2.95), Inches(0.38), "Chapter 1. AI의 본질 이해", fill=_rgb("#EEF2F7"), fg=T.muted) left_x = Inches(0.8) col_y = Inches(2.0) col_w = Inches(6.05) col_h = Inches(4.25) right_x = Inches(6.45) add_rect(s, left_x, col_y, col_w, col_h, fill=_rgb("#E9FBF1"), line=None, radius=True) add_rect(s, right_x, col_y, col_w, col_h, fill=_rgb("#FDECEC"), line=None, radius=True) add_textbox(s, left_x + Inches(0.35), col_y + Inches(0.3), col_w - Inches(0.7), Inches(0.35), "✓ AI가 잘하는 것", size=20, bold=True, color=_rgb("#15803D")) add_textbox(s, right_x + Inches(0.35), col_y + Inches(0.3), col_w - Inches(0.7), Inches(0.35), "✕ AI가 못하는 것 / 주의", size=20, bold=True, color=_rgb("#B91C1C")) good = [ "구조화된 글 작성 및 요약", "번역 및 언어 변환", "패턴 인식 및 분류", "코드 생성 및 디버깅", "반복 업무 자동화", "대용량 문서 핵심 추출", ] bad = [ "최신 실시간 정보 확인 (검색 미연동 시)", "복잡한 수학 계산·논리적 검증", "사용자의 숨겨진 의도 자동 파악", "사실 여부 100% 보장 (환각 위험)", "인간적 감각·경험 기반의 판단", "결과물에 대한 법적 책임", ] add_bullets(s, left_x + Inches(0.55), col_y + Inches(0.9), col_w - Inches(1.1), col_h - Inches(1.2), good, size=16, color=T.text) add_bullets(s, right_x + Inches(0.55), col_y + Inches(0.9), col_w - Inches(1.1), col_h - Inches(1.2), bad, size=16, color=T.text) # Center VS bubble vs = s.shapes.add_shape(MSO_AUTO_SHAPE_TYPE.OVAL, Inches(6.1), Inches(3.8), Inches(0.7), Inches(0.7)) vs.fill.solid() vs.fill.fore_color.rgb = _rgb("#EEF2F7") vs.line.color.rgb = T.line vs.text_frame.text = "VS" vs.text_frame.paragraphs[0].alignment = PP_ALIGN.CENTER vs.text_frame.paragraphs[0].runs[0].font.name = T.font_bold vs.text_frame.paragraphs[0].runs[0].font.bold = True vs.text_frame.paragraphs[0].runs[0].font.size = Pt(14) vs.text_frame.paragraphs[0].runs[0].font.color.rgb = T.muted # Bottom callout add_rect(s, Inches(0.7), Inches(6.55), Inches(11.93), Inches(0.65), fill=T.navy_2, line=None, radius=True) add_textbox( s, Inches(0.95), Inches(6.66), Inches(11.4), Inches(0.42), "AI를 \"잘 쓴다\"는 것은, AI가 못하는 영역을 사람이 보완한다는 뜻입니다.", size=16, bold=True, color=_rgb("#E5E7EB"), align=PP_ALIGN.CENTER, ) add_footer(s, 4, dark=False) def slide_05_hallucination(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "⚠ 왜 AI는 그럴듯하게 거짓말하는가?", size=14, bold=True, color=T.accent_red) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AI의 환각(Hallucination) 현상", size=40, bold=True, color=T.text) add_pill(s, Inches(11.2), Inches(1.05), Inches(1.55), Inches(0.4), "Critical Issue", fill=_rgb("#FEE2E2"), fg=_rgb("#B91C1C")) # Definition box add_rect(s, Inches(0.7), Inches(1.9), Inches(11.93), Inches(1.0), fill=_rgb("#F3F4F6"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(2.05), Inches(11.3), Inches(0.3), "환각(Hallucination)이란?", size=16, bold=True, color=T.text) add_textbox( s, Inches(1.0), Inches(2.35), Inches(11.3), Inches(0.5), "AI가 사실이 아닌 내용을 마치 사실인 것처럼 자신 있게 답하는 현상입니다.\n" "AI는 확률적으로 '자연스러운 문장'을 생성하는 과정에서 거짓 정보를 유창하게 만들어낼 수 있습니다.", size=13, bold=False, color=T.muted, line_spacing=1.2, ) # Risk cards x = Inches(0.7) y = Inches(3.1) w = Inches(3.82) h = Inches(1.55) g = Inches(0.35) def risk(xx, title, bullets): add_rect(s, xx, y, w, h, fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_textbox(s, xx + Inches(0.25), y + Inches(0.2), w - Inches(0.5), Inches(0.3), title, size=14, bold=True, color=_rgb("#B91C1C")) add_bullets(s, xx + Inches(0.25), y + Inches(0.55), w - Inches(0.5), h - Inches(0.6), bullets, size=12, color=_rgb("#7F1D1D")) risk(x, "가짜 정보 생성 사례", ["존재하지 않는 논문·자료 인용", "역사적 사실을 왜곡하여 설명", "없는 기능을 가진 것처럼 설명"]) risk(x + w + g, "수치 오류 사례", ["틀린 계산 결과를 정확한 척 제시", "단위(원, 달러) 혼동하여 표기", "최신 통계가 아닌 과거 데이터 인용"]) risk(x + (w + g) * 2, "법적/규정 위험 사례", ["개정 전 법률이나 규정을 답변", "저작권/라이선스 규정을 무시한 활용", "개인정보 보호 규정을 위반하는 제안"]) add_textbox(s, Inches(0.7), Inches(4.85), Inches(12), Inches(0.3), "✅ 환각을 피하는 3가지 습관", size=16, bold=True, color=_rgb("#15803D")) # Habits hy = Inches(5.2) hw = Inches(3.82) hh = Inches(1.1) def habit(xx, title, desc): add_rect(s, xx, hy, hw, hh, fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, xx + Inches(0.25), hy + Inches(0.25), hw - Inches(0.5), Inches(0.25), title, size=14, bold=True, color=_rgb("#15803D"), align=PP_ALIGN.CENTER) add_textbox(s, xx + Inches(0.25), hy + Inches(0.55), hw - Inches(0.5), Inches(0.4), desc, size=12, bold=False, color=_rgb("#166534"), align=PP_ALIGN.CENTER, line_spacing=1.2) habit(Inches(0.7), "원문 대조 확인", "중요한 수치·법률·사실 관계는\n반드시 원문 문서와 대조하세요.") habit(Inches(0.7) + hw + g, "출처 요청하기", "\"이 정보의 출처(URL)를 알려줘\"라고\n요청하여 근거를 확인하세요.") habit(Inches(0.7) + (hw + g) * 2, "'초안'으로만 활용", "AI 답변은 최종 결과물이 아닌\n'검토가 필요한 초안'으로 대하세요.") add_footer(s, 5, dark=False) def slide_06_prompt_definition(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 입력의 질이 출력의 질을 결정한다", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "프롬프트란 무엇인가?", size=40, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "AI와 소통하는 \"언어\" — 목적·상황·제약·형식을 한 번에 전달하는 지시서", size=16, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(2.1), Inches(12), Inches(0.3), "나쁜 프롬프트 vs 좋은 프롬프트 (예시 3가지)", size=16, bold=True, color=T.text) rows = [ ("보고서 써줘", "대상(누가 읽는지), 목적(왜), 형식(목차/분량)을 포함해서\n\"임원 보고용 1페이지 요약\"으로 작성해줘."), ("요약해줘", "\"다음 글을 3줄 요약 + 핵심 키워드 5개\" 형식으로 요약해줘."), ("분석해줘", "\"표로 정리(열: 문제, 원인, 영향, 개선안)\" 하고,\n결론을 먼저 제시한 뒤 근거를 번호로 달아줘."), ] y = Inches(2.5) for i, (bad, good) in enumerate(rows): yy = y + Inches(1.25) * i add_rect(s, Inches(0.7), yy, Inches(5.9), Inches(1.05), fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_rect(s, Inches(6.75), yy, Inches(5.88), Inches(1.05), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(0.95), yy + Inches(0.2), Inches(5.4), Inches(0.25), "❌ 나쁜 프롬프트", size=12, bold=True, color=_rgb("#B91C1C")) add_textbox(s, Inches(7.0), yy + Inches(0.2), Inches(5.4), Inches(0.25), "✅ 좋은 프롬프트", size=12, bold=True, color=_rgb("#15803D")) add_textbox(s, Inches(0.95), yy + Inches(0.5), Inches(5.4), Inches(0.5), bad, size=18, bold=True, color=_rgb("#7F1D1D")) add_textbox(s, Inches(7.0), yy + Inches(0.5), Inches(5.4), Inches(0.6), good, size=14, bold=False, color=_rgb("#166534"), line_spacing=1.15) add_footer(s, 6, dark=False) def slide_07_language(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 프롬프트 설계 원칙", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "[사례 1] 언어 선택: 한국어 vs 영어", size=34, bold=True, color=T.text) add_rect(s, Inches(0.7), Inches(1.9), Inches(11.93), Inches(2.3), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.15), Inches(11.3), Inches(0.3), "왜 영어 입력이 더 정확한 경우가 있는가?", size=18, bold=True, color=T.text) add_bullets( s, Inches(1.0), Inches(2.55), Inches(11.3), Inches(1.4), ["학습 데이터 불균형 (영어 데이터가 압도적으로 많음)", "전문 용어·기술 용어의 영어 표현이 더 풍부", "일부 모델/도구는 영어 지시에서 더 안정적으로 동작"], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.45), Inches(11.93), Inches(1.35), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.62), Inches(5.8), Inches(0.3), "실무 팁", size=14, bold=True, color=T.accent_yellow) add_textbox(s, Inches(1.0), Inches(4.92), Inches(6.6), Inches(0.7), "영어로 묻고, 한국어로 출력 요청하기\n예) \"Answer in Korean, and format as a table.\"", size=14, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2) add_textbox(s, Inches(8.0), Inches(4.75), Inches(4.4), Inches(0.9), "실습\n동일 질문 한/영 비교 결과 시연", size=16, bold=True, color=_rgb("#E5E7EB"), align=PP_ALIGN.CENTER, line_spacing=1.2) add_footer(s, 7, dark=False) def slide_08_context(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 프롬프트 설계 원칙", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "[사례 2] 정보의 완전성 — 맥락이 없으면 중의성이 생긴다", size=28, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "핵심 원리: \"목적 + 상황 + 제약 조건\"을 모두 포함하라", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(1.9), fill=T.white, line=T.line, radius=True) add_rect(s, Inches(0.7), Inches(2.05), Inches(5.8), Inches(1.9), fill=_rgb("#FFF1F2"), line=None, radius=True) add_rect(s, Inches(6.83), Inches(2.05), Inches(5.8), Inches(1.9), fill=_rgb("#E9FBF1"), line=None, radius=True) add_textbox(s, Inches(1.05), Inches(2.25), Inches(5.2), Inches(0.3), "❌ 중의적", size=14, bold=True, color=_rgb("#B91C1C")) add_textbox(s, Inches(7.15), Inches(2.25), Inches(5.2), Inches(0.3), "✅ 명확", size=14, bold=True, color=_rgb("#15803D")) add_textbox(s, Inches(1.05), Inches(2.65), Inches(5.2), Inches(0.8), "\"세차장에 갑니다. 걸어갈까요?\"", size=22, bold=True, color=_rgb("#7F1D1D"), line_spacing=1.1) add_textbox(s, Inches(7.15), Inches(2.65), Inches(5.2), Inches(0.8), "\"세차하러 갑니다. 걸어갈까요?\"", size=22, bold=True, color=_rgb("#166534"), line_spacing=1.1) add_textbox(s, Inches(1.05), Inches(3.35), Inches(5.2), Inches(0.4), "목적이 빠지면 해석이 여러 개로 갈립니다.", size=14, bold=False, color=_rgb("#7F1D1D")) add_textbox(s, Inches(7.15), Inches(3.35), Inches(5.2), Inches(0.4), "목적을 넣으면 AI도 명확히 답합니다.", size=14, bold=False, color=_rgb("#166534")) add_rect(s, Inches(0.7), Inches(4.2), Inches(11.93), Inches(1.85), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.35), Inches(11.3), Inches(0.3), "실무 적용", size=14, bold=True, color=T.accent_yellow) add_bullets( s, Inches(1.0), Inches(4.7), Inches(11.3), Inches(1.2), ["보고서/기획서 요청 시: \"누가 읽는지\"(대상) + \"목적\" + \"형식(분량/목차)\"을 함께 제공", "제약 조건(기간/데이터 범위/금지사항)을 명시하면 결과가 안정적으로 개선"], size=15, color=_rgb("#E5E7EB"), ) add_footer(s, 8, dark=False) def slide_09_5w1h(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 프롬프트 설계 원칙", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "5W1H 프롬프트 프레임", size=40, bold=True, color=T.text) frame = [ ("Who", "역할 설정", "예: \"너는 제약업계 10년 경력의 마케터야\""), ("What", "원하는 산출물", "예: \"임원 보고용 1페이지 요약\""), ("Why", "목적·배경", "예: \"AX 과제 선정 회의 자료로 사용할 거야\""), ("When/Where", "상황·컨텍스트", "예: \"지난 분기 데이터 기준, 국내 시장\""), ("How", "출력 형식", "예: \"표(열: 항목, 근거, 리스크) + 결론 먼저\""), ] y = Inches(2.0) row_h = Inches(0.95) for i, (k, t, ex) in enumerate(frame): yy = y + row_h * i add_rect(s, Inches(0.7), yy, Inches(11.93), row_h - Inches(0.12), fill=T.white, line=T.line, radius=True) add_rect(s, Inches(0.7), yy, Inches(1.6), row_h - Inches(0.12), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(0.7), yy + Inches(0.18), Inches(1.6), Inches(0.3), k, size=16, bold=True, color=T.accent_yellow, align=PP_ALIGN.CENTER) add_textbox(s, Inches(2.45), yy + Inches(0.18), Inches(3.2), Inches(0.3), t, size=18, bold=True, color=T.text) add_textbox(s, Inches(2.45), yy + Inches(0.5), Inches(9.9), Inches(0.35), ex, size=14, bold=False, color=T.muted) add_footer(s, 9, dark=False) def slide_10_format(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 프롬프트 설계 원칙", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "출력 형식을 지정하라", size=40, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "형식을 안 주면 AI가 알아서 결정 → 원하는 형태가 아닐 수 있음", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(5.9), Inches(3.0), fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_rect(s, Inches(6.75), Inches(2.05), Inches(5.88), Inches(3.0), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(0.95), Inches(2.25), Inches(5.4), Inches(0.3), "Before", size=14, bold=True, color=_rgb("#B91C1C")) add_textbox(s, Inches(7.0), Inches(2.25), Inches(5.4), Inches(0.3), "After", size=14, bold=True, color=_rgb("#15803D")) add_textbox(s, Inches(0.95), Inches(2.65), Inches(5.4), Inches(1.0), "\"이 자료 분석해줘\"", size=22, bold=True, color=_rgb("#7F1D1D")) add_textbox( s, Inches(7.0), Inches(2.65), Inches(5.4), Inches(1.4), "\"표로 만들어줘 (열: 항목명, 장점, 단점)\"\n\"3줄 요약으로\"\n\"결론 먼저, 근거는 번호 순으로\"", size=16, bold=True, color=_rgb("#166534"), line_spacing=1.2, ) add_rect(s, Inches(0.7), Inches(5.25), Inches(11.93), Inches(1.1), fill=_rgb("#24364D"), line=None, radius=True) add_textbox( s, Inches(1.0), Inches(5.4), Inches(11.3), Inches(0.8), "체크포인트\n- 형식(표/글머리/단계)\n- 분량(3줄/1페이지)\n- 순서(결론 먼저)\n- 톤(전문/간결/친절)", size=14, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.15, ) add_footer(s, 10, dark=False) def slide_11_role(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 2. 프롬프트 설계 원칙", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "역할 부여(Role Prompting) 기법", size=36, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "\"너는 ○○이야\" 선언의 효과: 관점·깊이·어조를 통제", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(2.1), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.25), Inches(11.3), Inches(0.3), "예시", size=14, bold=True, color=T.muted) add_rect(s, Inches(1.0), Inches(2.6), Inches(11.3), Inches(1.35), fill=_rgb("#24364D"), line=None, radius=True) add_textbox( s, Inches(1.3), Inches(2.75), Inches(10.7), Inches(1.0), "너는 대웅제약 CFO야.\n다음 데이터를 분석해줘. (목표: 비용 절감 관점, 리스크 포함, 1페이지 요약)", size=18, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2, ) add_rect(s, Inches(0.7), Inches(4.35), Inches(11.93), Inches(2.0), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(1.0), Inches(4.55), Inches(11.3), Inches(0.3), "실습", size=14, bold=True, color=_rgb("#15803D")) add_bullets( s, Inches(1.0), Inches(4.9), Inches(11.3), Inches(1.3), ["동일 데이터를 영업팀장 / 재무팀장 / CEO 역할로 각각 분석", "출력의 관점·강조점·결론이 어떻게 달라지는지 비교"], size=16, color=_rgb("#166534"), ) add_footer(s, 11, dark=False) def slide_12_steps(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 3. AI를 더 똑똑하게 쓰는 고급 기법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "단계적 사고 유도", size=40, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "복잡한 문제일수록 절차(단계)를 나눠서 요청하면 결과가 좋아집니다.", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.0), Inches(11.93), Inches(1.8), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.2), Inches(11.3), Inches(0.3), "좋은 요청 방식", size=14, bold=True, color=T.muted) add_bullets( s, Inches(1.0), Inches(2.55), Inches(11.3), Inches(1.1), ["\"문제를 단계별로 해결 절차로 나눠서 제시해줘\"", "\"각 단계마다 체크리스트를 만들고, 누락된 정보를 질문해줘\"", "\"최종 답변은 마지막에 요약해줘\""], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.05), Inches(11.93), Inches(2.3), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.25), Inches(11.3), Inches(0.3), "예시 (AX 과제 선정 기준 적용)", size=14, bold=True, color=T.accent_yellow) add_textbox( s, Inches(1.0), Inches(4.55), Inches(11.3), Inches(1.6), "과제 후보 3개를 아래 체크리스트 7개 기준으로 하나씩 평가해줘.\n" "1) 목표 명확성 2) 데이터 확보 가능성 3) 기대효과(정량/정성)\n" "4) 구현 난이도 5) 리스크(보안/규정) 6) 확장성 7) 일정 적합성\n" "출력: 표(열: 기준, 평가, 근거, 리스크) + 결론(우선순위) 먼저", size=15, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2, ) add_footer(s, 12, dark=False) def slide_13_fewshot(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 3. 고급 기법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "예시 제공 (Few‑Shot Prompting)", size=34, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "\"이런 식으로 해줘\" — 예시 1~3개의 위력", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.0), Inches(11.93), Inches(2.25), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.2), Inches(11.3), Inches(0.3), "효과", size=14, bold=True, color=T.muted) add_bullets(s, Inches(1.0), Inches(2.55), Inches(11.3), Inches(1.5), ["출력 형식, 어조, 수준을 예시로 통제", "모호한 요구를 '정답 샘플'로 명확히 전달", "팀 내 산출물 스타일을 표준화"], size=16, color=T.text) add_rect(s, Inches(0.7), Inches(4.45), Inches(11.93), Inches(1.9), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(1.0), Inches(4.65), Inches(11.3), Inches(0.3), "[사례 3] 응용", size=14, bold=True, color=_rgb("#15803D")) add_textbox( s, Inches(1.0), Inches(4.95), Inches(11.3), Inches(1.2), "`20260223_report_10.doc`를 예시로 제공 → 동일 형식의 보고서를 자동 생성\n" "프롬프트에 \"예시 문서의 목차/톤/표현을 유지\" 조건을 포함", size=16, bold=True, color=_rgb("#166534"), line_spacing=1.2, ) add_footer(s, 13, dark=False) def slide_14_context_window(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 3. 고급 기법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "맥락 누적 활용 (Context Window 관리)", size=30, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "대화가 길어질수록 앞 조건을 잊을 수 있으니, 핵심 조건을 관리해야 합니다.", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(1.8), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.25), Inches(11.3), Inches(0.3), "실무 습관", size=14, bold=True, color=T.muted) add_bullets( s, Inches(1.0), Inches(2.6), Inches(11.3), Inches(1.2), ["중요한 조건은 대화 앞부분에 배치", "새 대화 시작 시 \"지금까지 정한 것\" 요약을 먼저 붙여넣기", "긴 문서는 분할(Chunk) + 요약 누적 전략 사용"], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.05), Inches(11.93), Inches(2.3), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.25), Inches(11.3), Inches(0.3), "분할 전략 예시", size=14, bold=True, color=T.accent_yellow) add_textbox( s, Inches(1.0), Inches(4.55), Inches(11.3), Inches(1.6), "1) 문서를 3~5페이지 단위로 나눠 요약 요청\n" "2) 각 요약을 '핵심 포인트/결정사항/숫자' 위주로 정리\n" "3) 마지막에 모든 요약을 합쳐 최종 보고서 작성 요청", size=16, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2, ) add_footer(s, 14, dark=False) def slide_15_iterative(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 3. 고급 기법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "반복 정제 (Iterative Refinement)", size=34, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "첫 번째 답이 완벽할 필요는 없습니다. 초안 → 피드백 → 확정", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(2.0), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.25), Inches(11.3), Inches(0.3), "자주 쓰는 후속 프롬프트", size=14, bold=True, color=T.muted) add_bullets( s, Inches(1.0), Inches(2.6), Inches(11.3), Inches(1.3), ["\"더 간결하게\"", "\"3번 항목을 더 구체적으로\"", "\"전문적 어조로 바꿔줘\"", "\"표로 재구성해줘\"", "\"리스크/반론도 함께 제시해줘\""], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.25), Inches(11.93), Inches(2.1), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(1.0), Inches(4.45), Inches(11.3), Inches(0.3), "실무 비유", size=14, bold=True, color=_rgb("#15803D")) add_textbox( s, Inches(1.0), Inches(4.75), Inches(11.3), Inches(1.4), "AI는 탁월한 \"초안 작성자\"입니다.\n" "사람은 검토자(Reviewer)로서 방향을 잡고, 근거·수치·규정을 확인해 완성도를 올립니다.", size=18, bold=True, color=_rgb("#166534"), line_spacing=1.2, ) add_footer(s, 15, dark=False) def slide_16_files(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 3. 고급 기법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "파일·데이터 연동 활용", size=40, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "CSV, Excel, Word, PDF 등 정형/반정형 데이터를 먹이면 성능이 크게 개선됩니다.", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(2.35), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.25), Inches(11.3), Inches(0.3), "실무 예시", size=14, bold=True, color=T.muted) add_bullets( s, Inches(1.0), Inches(2.6), Inches(11.3), Inches(1.7), ["채용: 지원서(CSV) + 평가 기준(문서) → 자동 평가 코멘트 생성", "과제 선정: 신청 양식 + 프로세스 문서 → 기준별 점수/근거 표 생성", "성과 평가: KPI 테이블 + 코멘트 → 요약 및 이슈 탐지"], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.6), Inches(11.93), Inches(1.75), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.8), Inches(11.3), Inches(0.3), "포인트: 데이터 구조화", size=14, bold=True, color=T.accent_yellow) add_textbox( s, Inches(1.0), Inches(5.1), Inches(11.3), Inches(1.1), "AI는 정형 데이터(표/필드)를 더 잘 처리합니다.\n" "입력 데이터에 컬럼명, 단위, 기간, 정의를 명시하면 오류가 크게 줄어듭니다.", size=16, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2, ) add_footer(s, 16, dark=False) def slide_17_trust(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 4. 실수하지 않는 AI 활용법", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AI를 믿어야 할 때 vs 검증해야 할 때", size=28, bold=True, color=T.text) add_rect(s, Inches(0.7), Inches(1.9), Inches(5.9), Inches(4.45), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_rect(s, Inches(6.75), Inches(1.9), Inches(5.88), Inches(4.45), fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_textbox(s, Inches(0.95), Inches(2.15), Inches(5.4), Inches(0.35), "믿어도 되는 경우", size=18, bold=True, color=_rgb("#15803D")) add_textbox(s, Inches(7.0), Inches(2.15), Inches(5.4), Inches(0.35), "반드시 검증", size=18, bold=True, color=_rgb("#B91C1C")) add_bullets(s, Inches(0.95), Inches(2.6), Inches(5.4), Inches(3.6), ["형식 작업(문장 다듬기, 문서 구성)", "요약, 번역", "초안 작성(메일/보고서)", "코드 생성(단, 테스트/리뷰 필수)"], size=16, color=_rgb("#166534")) add_bullets(s, Inches(7.0), Inches(2.6), Inches(5.4), Inches(3.6), ["수치·통계", "법률·규정", "최신 정보", "사람 이름/조직명", "의사결정에 영향을 주는 사실"], size=16, color=_rgb("#7F1D1D")) add_rect(s, Inches(0.7), Inches(6.55), Inches(11.93), Inches(0.65), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(6.68), Inches(11.3), Inches(0.4), "\"AI가 틀렸다\"가 아니라 \"내가 확인하지 않았다\"", size=18, bold=True, color=_rgb("#E5E7EB"), align=PP_ALIGN.CENTER) add_footer(s, 17, dark=False) def slide_18_security(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 4. 보안과 개인정보", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "무엇을 넣으면 안 되는가", size=40, bold=True, color=T.text) add_rect(s, Inches(0.7), Inches(1.9), Inches(11.93), Inches(2.45), fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_textbox(s, Inches(1.0), Inches(2.1), Inches(11.3), Inches(0.3), "입력 금지", size=16, bold=True, color=_rgb("#B91C1C")) add_bullets(s, Inches(1.0), Inches(2.45), Inches(11.3), Inches(1.8), ["사내 기밀 데이터", "개인식별정보(PII): 이름/주민번호/연락처/계좌/주소 등", "고객·환자·직원 데이터 원문", "계약서/특허 등 민감 문서의 원문"], size=16, color=_rgb("#7F1D1D")) add_rect(s, Inches(0.7), Inches(4.55), Inches(11.93), Inches(1.8), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(1.0), Inches(4.75), Inches(11.3), Inches(0.3), "대안", size=16, bold=True, color=_rgb("#15803D")) add_bullets(s, Inches(1.0), Inches(5.1), Inches(11.3), Inches(1.1), ["가명화/익명화 후 활용 (ID 치환, 숫자 범위화)", "내부/사내 AI 툴 사용 여부 확인", "필요 최소 정보만 제공 + 출력은 요약 중심"], size=16, color=_rgb("#166534")) add_footer(s, 18, dark=False) def slide_19_copyright(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 4. 저작권과 책임", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AI 결과물의 저작권과 책임", size=36, bold=True, color=T.text) add_rect(s, Inches(0.7), Inches(1.9), Inches(11.93), Inches(4.45), fill=T.white, line=T.line, radius=True) add_bullets( s, Inches(1.0), Inches(2.2), Inches(11.3), Inches(3.8), ["AI 생성물의 법적 지위는 국가/시점/정책에 따라 달라질 수 있음", "출처 표기와 사실 확인의 의무는 사용자에게 있음", "최종 결과물에 대한 책임은 항상 사람에게", "사내 가이드라인(대웅그룹 AI 활용 가이드라인)과 연계해 준수"], size=18, color=T.text, ) add_footer(s, 19, dark=False) def slide_20_skills(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 4. 역량 재정의", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AI 환경에서의 직무 역량 재정의", size=30, bold=True, color=T.text) add_rect(s, Inches(0.7), Inches(1.9), Inches(5.9), Inches(4.45), fill=_rgb("#FFF1F2"), line=_rgb("#FECACA"), radius=True) add_rect(s, Inches(6.75), Inches(1.9), Inches(5.88), Inches(4.45), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(0.95), Inches(2.15), Inches(5.4), Inches(0.35), "상대적으로 약해지는 역량", size=16, bold=True, color=_rgb("#B91C1C")) add_textbox(s, Inches(7.0), Inches(2.15), Inches(5.4), Inches(0.35), "더 중요해지는 역량", size=16, bold=True, color=_rgb("#15803D")) add_bullets(s, Inches(0.95), Inches(2.55), Inches(5.4), Inches(3.7), ["단순 요약/정리", "반복 문서 작성", "기본 번역", "정형 보고서 초안"], size=16, color=_rgb("#7F1D1D")) add_bullets(s, Inches(7.0), Inches(2.55), Inches(5.4), Inches(3.7), ["문제 정의와 목표 설정", "좋은 질문(프롬프트) 설계", "검증·리스크 관리", "의사결정과 책임", "업무 프로세스 설계(워크플로우)"], size=16, color=_rgb("#166534")) add_rect(s, Inches(0.7), Inches(6.55), Inches(11.93), Inches(0.65), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(6.68), Inches(11.3), Inches(0.4), "\"AI에게 좋은 질문을 하는 능력\" = 새로운 핵심 역량", size=18, bold=True, color=_rgb("#E5E7EB"), align=PP_ALIGN.CENTER) add_footer(s, 20, dark=False) def slide_21_scenarios(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 5. 실전 적용 — 대웅 AX 과제와 연결", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "부서별 AI 활용 시나리오 맵", size=40, bold=True, color=T.text) cards = [ ("영업", ["채권 현황 조회", "인사이트 자동 생성"], T.accent_blue), ("마케팅", ["대시보드 결산 자동 작성", "기사/콘텐츠 초안 생성"], T.accent_yellow), ("재무/회계", ["지출 증빙 검토 자동화", "이상 지출 탐지"], T.accent_green), ("연구개발", ["특허·논문 요약", "보고서 초안"], _rgb("#A855F7")), ("HR", ["면접 분석", "교육 콘텐츠 생성"], T.accent_red), ] x0 = Inches(0.7) y0 = Inches(2.0) w = Inches(3.82) h = Inches(1.75) g = Inches(0.35) positions = [ (x0, y0), (x0 + w + g, y0), (x0 + (w + g) * 2, y0), (x0 + w / 2 + g / 2, y0 + h + g), (x0 + (w + g) * 1.5, y0 + h + g), ] for (title, lines, accent), (xx, yy) in zip(cards, positions, strict=True): add_rect(s, xx, yy, w, h, fill=T.white, line=T.line, radius=True) add_rect(s, xx, yy, w, Inches(0.08), fill=accent, line=None) add_textbox(s, xx + Inches(0.25), yy + Inches(0.35), w - Inches(0.5), Inches(0.3), title, size=18, bold=True, color=T.text) add_bullets(s, xx + Inches(0.25), yy + Inches(0.75), w - Inches(0.5), Inches(0.9), lines, size=14, color=T.muted) add_footer(s, 21, dark=False) def slide_22_ax_application(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 5. 실전 적용", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "AX 과제 신청 단계에서의 AI 활용", size=32, bold=True, color=T.text) add_textbox(s, Inches(0.7), Inches(1.55), Inches(12), Inches(0.35), "신청서 작성 → 자기검토 → 평가 기준 정렬까지 한 번에", size=16, bold=True, color=T.muted) add_rect(s, Inches(0.7), Inches(2.05), Inches(11.93), Inches(2.25), fill=T.white, line=T.line, radius=True) add_textbox(s, Inches(1.0), Inches(2.25), Inches(11.3), Inches(0.3), "활용 포인트", size=14, bold=True, color=T.muted) add_bullets( s, Inches(1.0), Inches(2.6), Inches(11.3), Inches(1.6), ["신청서 작성 시 AI 도움받기: As‑Is → To‑Be 구조화", "과제 평가 기준에 맞는 자기검토(누락 항목 질문하도록)", "정량 효과/리스크(보안·규정)까지 포함해 완성도 향상"], size=16, color=T.text, ) add_rect(s, Inches(0.7), Inches(4.55), Inches(11.93), Inches(1.8), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(1.0), Inches(4.75), Inches(11.3), Inches(0.3), "데모 데이터", size=14, bold=True, color=T.accent_yellow) add_textbox( s, Inches(1.0), Inches(5.05), Inches(11.3), Inches(1.2), "`20260223.csv` + `AX추진프로세스.docx` → 자동 평가 보고서 생성 시연", size=18, bold=True, color=_rgb("#E5E7EB"), line_spacing=1.2, ) add_footer(s, 22, dark=False) def slide_23_routine(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.bg) add_textbox(s, Inches(0.7), Inches(0.55), Inches(12), Inches(0.3), "PART 5. 실전 적용", size=14, bold=True, color=T.muted) add_textbox(s, Inches(0.7), Inches(0.9), Inches(12), Inches(0.7), "나만의 AI 활용 루틴 만들기", size=40, bold=True, color=T.text) cards = [ ("Daily", "AI 초안 작성 → 내가 검토·수정", T.accent_blue), ("Weekly", "반복 업무 프롬프트 템플릿화", T.accent_green), ("Monthly", "AI 활용 성과 측정 (시간 절감, 품질)", T.accent_yellow), ] x = Inches(0.7) y = Inches(2.05) w = Inches(3.82) h = Inches(2.0) g = Inches(0.35) for i, (t, d, a) in enumerate(cards): xx = x + (w + g) * i add_rect(s, xx, y, w, h, fill=T.white, line=T.line, radius=True) add_rect(s, xx, y, w, Inches(0.08), fill=a, line=None) add_textbox(s, xx + Inches(0.25), y + Inches(0.45), w - Inches(0.5), Inches(0.3), t, size=18, bold=True, color=T.text) add_textbox(s, xx + Inches(0.25), y + Inches(0.85), w - Inches(0.5), Inches(0.9), d, size=16, bold=True, color=T.muted, line_spacing=1.2) add_rect(s, Inches(0.7), Inches(4.35), Inches(11.93), Inches(2.0), fill=_rgb("#E9FBF1"), line=_rgb("#BBF7D0"), radius=True) add_textbox(s, Inches(1.0), Inches(4.55), Inches(11.3), Inches(0.3), "권장", size=14, bold=True, color=_rgb("#15803D")) add_textbox(s, Inches(1.0), Inches(4.85), Inches(11.3), Inches(1.2), "프롬프트 라이브러리를 구축하세요.\n(업무별 템플릿 + 예시 + 검증 체크리스트)", size=20, bold=True, color=_rgb("#166534"), line_spacing=1.2) add_footer(s, 23, dark=False) def slide_24_closing(prs: Presentation) -> None: s = prs.slides.add_slide(prs.slide_layouts[6]) set_slide_bg(s, T.navy) add_textbox(s, Inches(0.7), Inches(0.7), Inches(12), Inches(0.4), "PART 5. 마무리", size=14, bold=True, color=_rgb("#D1D5DB")) add_textbox(s, Inches(0.7), Inches(1.1), Inches(12), Inches(0.9), "AI와 함께 일하는 미래", size=46, bold=True, color=T.white) add_rect(s, Inches(0.7), Inches(2.15), Inches(11.93), Inches(0.05), fill=T.accent_yellow, line=None) add_textbox(s, Inches(0.7), Inches(2.35), Inches(12), Inches(0.6), "AI는 대체자가 아닌 증폭기(Amplifier)", size=28, bold=True, color=T.accent_yellow) add_bullets( s, Inches(0.9), Inches(3.2), Inches(12), Inches(2.0), ["잘 쓰는 사람과 못 쓰는 사람의 격차는 계속 벌어진다", "지금 시작하는 것이 가장 빠른 것", "핵심은: 목적·맥락·제약·형식 + 검증"], size=20, color=_rgb("#E5E7EB"), ) add_rect(s, Inches(0.7), Inches(5.7), Inches(11.93), Inches(0.9), fill=_rgb("#24364D"), line=None, radius=True) add_textbox(s, Inches(0.7), Inches(5.9), Inches(11.93), Inches(0.5), "Q&A / 다음 학습 자원 안내", size=26, bold=True, color=T.white, align=PP_ALIGN.CENTER) add_footer(s, 24, dark=True) def build_ppt() -> Presentation: prs = Presentation() prs.slide_width = SLIDE_W prs.slide_height = SLIDE_H # Slides 1-5 (re-created as editable) slide_01_cover(prs) slide_02_core_assumptions(prs) slide_03_llm(prs) slide_04_good_vs_bad(prs) slide_05_hallucination(prs) # Slides 6-24 per outline slide_06_prompt_definition(prs) slide_07_language(prs) slide_08_context(prs) slide_09_5w1h(prs) slide_10_format(prs) slide_11_role(prs) slide_12_steps(prs) slide_13_fewshot(prs) slide_14_context_window(prs) slide_15_iterative(prs) slide_16_files(prs) slide_17_trust(prs) slide_18_security(prs) slide_19_copyright(prs) slide_20_skills(prs) slide_21_scenarios(prs) slide_22_ax_application(prs) slide_23_routine(prs) slide_24_closing(prs) return prs def validate(prs: Presentation) -> None: if len(prs.slides) != 24: raise ValueError(f"expected 24 slides, got {len(prs.slides)}") # Ensure no full-slide raster images are used (editable requirement) from pptx.enum.shapes import MSO_SHAPE_TYPE pics = 0 for slide in prs.slides: for sh in slide.shapes: if sh.shape_type == MSO_SHAPE_TYPE.PICTURE: pics += 1 if pics != 0: raise ValueError(f"expected 0 picture shapes, got {pics}") def main() -> None: base_dir = Path(__file__).resolve().parent out = base_dir / "outputs" / "ai_work.pptx" out.parent.mkdir(parents=True, exist_ok=True) prs = build_ppt() validate(prs) prs.save(str(out)) print(f"wrote {out} ({out.stat().st_size:,} bytes)") if __name__ == "__main__": main()