| """ |
| Create a fixed layout PPT for India AI Impact Buildathon. |
| Fixes overlap issues by deleting old placeholders and creating new, precisely positioned text boxes. |
| """ |
| from pathlib import Path |
| from pptx import Presentation |
| from pptx.util import Inches, Pt |
| from pptx.enum.text import PP_ALIGN, MSO_ANCHOR |
| from pptx.dml.color import RGBColor |
|
|
| ROOT = Path(__file__).resolve().parent.parent |
| PPT_DIR = ROOT / "PPT" |
| TEMPLATE_PATH = PPT_DIR / "India AI Impact Buildathon - Sample PPT.pptx" |
| OUTPUT_PATH = PPT_DIR / "ScamShield_AI_Final_Submission.pptx" |
|
|
| |
| WIDTH = Inches(10) |
| HEIGHT = Inches(5.625) |
|
|
| def clean_slide_content(slide): |
| """ |
| Removes all shapes except the title and footer/slide number. |
| Returns the title shape if found. |
| """ |
| title_shape = None |
| shapes_to_delete = [] |
| |
| |
| for shape in slide.shapes: |
| |
| if hasattr(shape, "text_frame") and shape == slide.shapes.title: |
| title_shape = shape |
| continue |
| |
| |
| try: |
| if hasattr(shape, "placeholder_format"): |
| if shape.placeholder_format.type == 1: |
| title_shape = shape |
| continue |
| except ValueError: |
| pass |
| |
| |
| |
| if shape.has_text_frame: |
| |
| |
| |
| shapes_to_delete.append(shape) |
| |
| |
| if shape.shape_type == 13: |
| |
| if shape.top > Inches(1.5) and shape.top < Inches(4.5): |
| shapes_to_delete.append(shape) |
|
|
| |
| |
| |
| for shape in shapes_to_delete: |
| if shape.has_text_frame: |
| shape.text_frame.clear() |
| |
| shape.left = Inches(20) |
| |
| return title_shape |
|
|
| def add_text_box(slide, text, left, top, width, height, font_size=12, bold=False, color=None, alignment=None): |
| textbox = slide.shapes.add_textbox(left, top, width, height) |
| text_frame = textbox.text_frame |
| text_frame.word_wrap = True |
| |
| p = text_frame.paragraphs[0] |
| p.text = text |
| p.font.size = Pt(font_size) |
| if bold: |
| p.font.bold = True |
| if color: |
| p.font.color.rgb = color |
| if alignment: |
| p.alignment = alignment |
| |
| return textbox |
|
|
| def add_bullet_text(slide, title, bullets, left, top, width, height): |
| textbox = slide.shapes.add_textbox(left, top, width, height) |
| text_frame = textbox.text_frame |
| text_frame.word_wrap = True |
| |
| |
| p = text_frame.paragraphs[0] |
| p.text = title |
| p.font.size = Pt(14) |
| p.font.bold = True |
| p.space_after = Pt(6) |
| |
| |
| for bullet in bullets: |
| p = text_frame.add_paragraph() |
| p.text = bullet |
| p.font.size = Pt(11) |
| p.level = 0 |
| p.space_before = Pt(3) |
|
|
| def main(): |
| print(f"Opening template: {TEMPLATE_PATH}") |
| prs = Presentation(str(TEMPLATE_PATH)) |
| |
| |
| |
| |
| slide = prs.slides[0] |
| clean_slide_content(slide) |
| |
| |
| |
| add_text_box(slide, "INDIA AI IMPACT BUILDATHON", Inches(1), Inches(1.5), Inches(8), Inches(1), |
| font_size=32, bold=True, alignment=PP_ALIGN.CENTER) |
| add_text_box(slide, "Challenge 2: Agentic Honeypot for Scam Detection", Inches(1), Inches(2.5), Inches(8), Inches(1), |
| font_size=20, alignment=PP_ALIGN.CENTER, color=RGBColor(100, 100, 100)) |
| add_text_box(slide, "Team: ScamShield AI", Inches(1), Inches(3.5), Inches(8), Inches(0.5), |
| font_size=16, alignment=PP_ALIGN.CENTER) |
|
|
| |
| |
| |
| slide = prs.slides[1] |
| clean_slide_content(slide) |
| |
| |
| add_text_box(slide, "[PLACE TEAM LOGO HERE]", Inches(4), Inches(1), Inches(2), Inches(1), |
| font_size=10, alignment=PP_ALIGN.CENTER) |
| |
| |
| add_text_box(slide, "ScamShield AI", Inches(1), Inches(2.2), Inches(8), Inches(1), |
| font_size=36, bold=True, alignment=PP_ALIGN.CENTER, color=RGBColor(0, 51, 102)) |
| |
| |
| tagline = ("An autonomous agentic honeypot system that detects scam messages, " |
| "engages scammers with believable AI personas, and extracts actionable " |
| "intelligence (UPI, Bank Accounts, Links).") |
| add_text_box(slide, tagline, Inches(1.5), Inches(3.2), Inches(7), Inches(1.5), |
| font_size=16, alignment=PP_ALIGN.CENTER) |
|
|
| |
| |
| |
| slide = prs.slides[2] |
| clean_slide_content(slide) |
| add_text_box(slide, "1) THE PROBLEM", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| y_start = Inches(1.5) |
| w_col = Inches(2.8) |
| gap = Inches(0.3) |
| h_col = Inches(3.5) |
| |
| |
| add_bullet_text(slide, "๐จ What is happening?", [ |
| "500,000+ scam calls/msgs daily", |
| "โน60+ crore daily losses", |
| "47% Indians affected", |
| "Target: UPI, Loans, KYC" |
| ], Inches(0.5), y_start, w_col, h_col) |
| |
| |
| add_bullet_text(slide, "โ ๏ธ Why is it a problem?", [ |
| "Passive detection fails", |
| "Scammers evolve fast", |
| "No intelligence gathered", |
| "Citizens feel helpless" |
| ], Inches(0.5 + w_col + gap), y_start, w_col, h_col) |
| |
| |
| add_bullet_text(slide, "๐ฅ Who is affected?", [ |
| "Elderly & Non-tech savvy", |
| "Middle-class families", |
| "Banks (Reputation loss)", |
| "Law Enforcement (Overload)" |
| ], Inches(0.5 + 2*(w_col + gap)), y_start, w_col, h_col) |
|
|
| |
| |
| |
| slide = prs.slides[3] |
| clean_slide_content(slide) |
| add_text_box(slide, "2) OUR SOLUTION", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| |
| left_m = Inches(0.8) |
| top_m = Inches(1.2) |
| box_w = Inches(4.0) |
| box_h = Inches(1.8) |
| h_gap = Inches(0.4) |
| v_gap = Inches(0.3) |
| |
| |
| add_bullet_text(slide, "๐ฏ Detection", [ |
| "IndicBERT + Rules", |
| "Hindi, English, Hinglish", |
| "90%+ Accuracy Target" |
| ], left_m, top_m, box_w, box_h) |
| |
| |
| add_bullet_text(slide, "๐ค Engagement", [ |
| "LangGraph Agent", |
| "Dynamic Personas (Elderly, Eager)", |
| "Up to 20 turns conversation" |
| ], left_m + box_w + h_gap, top_m, box_w, box_h) |
| |
| |
| add_bullet_text(slide, "๐ Extraction", [ |
| "Extracts UPI, Bank, IFSC", |
| "Captures Phishing Links", |
| "Structured JSON Output" |
| ], left_m, top_m + box_h + v_gap, box_w, box_h) |
| |
| |
| add_bullet_text(slide, "๐ Integration", [ |
| "REST API Endpoint", |
| "Mock Scammer API Ready", |
| "Dockerized & Scalable" |
| ], left_m + box_w + h_gap, top_m + box_h + v_gap, box_w, box_h) |
|
|
| |
| |
| |
| slide = prs.slides[4] |
| clean_slide_content(slide) |
| add_text_box(slide, "3) HOW IT WORKS", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| |
| flow_text = ( |
| "STEP 1: INPUT\n" |
| "Message arrives: \"You won 10 lakh! Send OTP.\"\n\n" |
| "STEP 2: DECISION (AI)\n" |
| "Confidence > 70%? Yes -> Trigger Honeypot\n\n" |
| "STEP 3: ENGAGE\n" |
| "Agent (Persona): \"Oh wow! How do I get it?\"\n\n" |
| "STEP 4: EXTRACT & OUTPUT\n" |
| "Scammer shares UPI -> We capture it -> JSON Report" |
| ) |
| add_text_box(slide, flow_text, Inches(1), Inches(1.5), Inches(8), Inches(3.5), font_size=14) |
| |
| |
| add_text_box(slide, "Simple Flow: Message In โก๏ธ Scam Check โก๏ธ Fake Victim Talks โก๏ธ Proof Extracted", |
| Inches(0.5), Inches(5.0), Inches(9), Inches(0.5), font_size=12, bold=True, alignment=PP_ALIGN.CENTER, color=RGBColor(0, 102, 204)) |
|
|
| |
| |
| |
| slide = prs.slides[5] |
| clean_slide_content(slide) |
| add_text_box(slide, "4) PROOF IT WORKS", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| |
| proofs = [ |
| ("โ
Live API Demo", "POST /honeypot/engage works in <2s"), |
| ("๐ Test Metrics", "Validated on 100+ scam samples"), |
| ("๐ฎ๐ณ Real Context", "Handles Hindi/Hinglish perfectly"), |
| ("๐ก๏ธ Extraction", "Success: Captured UPIs & Links") |
| ] |
| |
| y_pos = Inches(1.4) |
| for title, desc in proofs: |
| add_text_box(slide, title, Inches(1), y_pos, Inches(3), Inches(0.5), font_size=16, bold=True) |
| add_text_box(slide, desc, Inches(4.2), y_pos, Inches(5), Inches(0.5), font_size=14) |
| y_pos += Inches(0.9) |
|
|
| |
| |
| |
| slide = prs.slides[6] |
| clean_slide_content(slide) |
| add_text_box(slide, "5) A NUANCE WE HANDLED", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| y_start = Inches(1.5) |
| box_h = Inches(3.5) |
| box_w = Inches(2.8) |
| |
| add_bullet_text(slide, "๐ Mixed Language", [ |
| "Handles Code-Mixing", |
| "(Hindi + English)", |
| "IndicBERT trained on Indian datasets" |
| ], Inches(0.5), y_start, box_w, box_h) |
| |
| add_bullet_text(slide, "๐ Over-Polite Scams", [ |
| "Personas don't get suspicious", |
| "Elderly/Confused tones", |
| "Matches scammer's pace" |
| ], Inches(0.5 + box_w + gap), y_start, box_w, box_h) |
| |
| add_bullet_text(slide, "๐ Persistence", [ |
| "Redis Session State", |
| "Remembers Context", |
| "Engages for 10+ turns" |
| ], Inches(0.5 + 2*(box_w + gap)), y_start, box_w, box_h) |
|
|
| |
| |
| |
| slide = prs.slides[7] |
| clean_slide_content(slide) |
| add_text_box(slide, "6) TRADE-OFF & 7) FAILURE CASE", Inches(0.5), Inches(0.4), Inches(9), Inches(0.6), font_size=24, bold=True) |
| |
| |
| add_bullet_text(slide, "โ๏ธ Trade-Off: Depth vs Speed", [ |
| "Choice: Maximize engagement depth", |
| "Why: More turns = More Intelligence", |
| "Cost: Higher latency (1-2s)", |
| "Not optimized for instant blocking" |
| ], Inches(0.8), Inches(1.5), Inches(4), Inches(3.5)) |
| |
| |
| add_bullet_text(slide, "โ Failure Case: Short Convos", [ |
| "Struggle: Scammer stops after 1 msg", |
| "Result: No intelligence extracted", |
| "Mitigation: 'Eager' persona to bait", |
| "Struggle: Novel templates (Low Conf)" |
| ], Inches(5.2), Inches(1.5), Inches(4), Inches(3.5)) |
|
|
| |
| |
| |
| slide = prs.slides[8] |
| clean_slide_content(slide) |
| |
| |
| add_text_box(slide, "SUBMISSION DETAILS", Inches(1), Inches(1), Inches(8), Inches(0.8), |
| font_size=28, bold=True, alignment=PP_ALIGN.CENTER) |
| |
| |
| info_text = ( |
| "Team: ScamShield AI\n" |
| "Challenge 2: Agentic Honeypot\n" |
| "Tech Stack: IndicBERT, LangGraph, Groq, FastAPI\n\n" |
| "Contact: missionupskillindia@hclguvi.com\n" |
| "Subject: ScamShield AI PPT || India AI Impact Buildathon\n" |
| "Deadline: 13th Feb 2026" |
| ) |
| add_text_box(slide, info_text, Inches(2), Inches(2.2), Inches(6), Inches(3), |
| font_size=16, alignment=PP_ALIGN.CENTER) |
|
|
| |
| OUTPUT_PATH.parent.mkdir(parents=True, exist_ok=True) |
| prs.save(str(OUTPUT_PATH)) |
| print(f"SUCCESS: Fixed Layout PPT created: {OUTPUT_PATH}") |
|
|
| if __name__ == "__main__": |
| main() |
|
|