usmanyousaf's picture
Create app.py
b8d2837 verified
import streamlit as st
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.dml.color import RGBColor
import io, tempfile, os, re
from transformers import pipeline
# ── CONFIG ─────────────────────────────────────────────────────
st.set_page_config(page_title="PPTX Smart Enhancer", layout="wide")
MODEL_ID = "Faisalkhany/newfinetune" # ← your HF model
pipe = pipeline("text2text-generation", model=MODEL_ID)
TEMPLATES = {
"Office Default": {
"font": "Calibri",
"colors": {"primary":"#2B579A","secondary":"#5B9BD5","text":"#000000","background":"#FFFFFF"},
"sizes": {"title":44,"heading":32,"body":18}, "background":True
},
"Modern Office": {
"font": "Segoe UI",
"colors": {"primary":"#404040","secondary":"#A5A5A5","text":"#FFFFFF","background":"#121212"},
"sizes": {"title":36,"heading":24,"body":16}, "background":True
},
"Corporate": {
"font":"Arial",
"colors":{"primary":"#1976D2","secondary":"#BBDEFB","text":"#212121","background":"#FAFAFA"},
"sizes":{"title":40,"heading":28,"body":18}, "background":False
}
}
FONT_CHOICES = {f:f for f in ["Arial","Calibri","Times New Roman","Segoe UI","Verdana","Georgia"]}
# ── HELPERS ────────────────────────────────────────────────────
def chunk_slide_text(text, max_words=200):
words = text.split()
return [" ".join(words[i:i+max_words]) for i in range(0, len(words), max_words)]
def get_ai_response(prompt: str) -> str:
out = pipe(prompt, max_length=512, truncation=True)
return out[0]["generated_text"]
def extract_slide_text(slide) -> str:
parts = []
for shp in slide.shapes:
if hasattr(shp, "text_frame"):
for p in shp.text_frame.paragraphs:
if p.text.strip():
parts.append(p.text.strip())
return "\n".join(parts)
def split_formatted_runs(text):
segments, cur, bold, italic = [], [], False, False
parts = re.split(r'(\*|_)', text)
for tok in parts:
if tok in ("*","_"):
if cur:
segments.append({"text":"".join(cur),"bold":bold,"italic":italic})
cur=[]
if tok=="*": bold=not bold
else: italic=not italic
else:
cur.append(tok)
if cur:
segments.append({"text":"".join(cur),"bold":bold,"italic":italic})
return segments
def apply_formatting(tf, content, ds):
tf.clear()
for line in [l for l in content.split("\n") if l.strip()]:
clean = re.sub(r'^#+\s*','', line).strip()
if re.match(r'^(What is|Understanding|Key|Conclusion)', clean, re.IGNORECASE):
p = tf.add_paragraph(); p.text=clean
p.font.size=Pt(ds["heading_size"]); p.font.bold=True; p.space_after=Pt(12)
continue
if re.match(r'^[\-\*\β€’] ', clean):
p=tf.add_paragraph(); p.level=0
txt = clean[2:].strip()
for seg in split_formatted_runs(txt):
r=p.add_run(); r.text=seg["text"]; r.font.bold=seg["bold"]; r.font.italic=seg["italic"]
p.font.size=Pt(ds["body_size"]); continue
p=tf.add_paragraph()
for seg in split_formatted_runs(clean):
r=p.add_run(); r.text=seg["text"]; r.font.bold=seg["bold"]; r.font.italic=seg["italic"]
p.font.size=Pt(ds["body_size"]); p.space_after=Pt(6)
def apply_design(slide, ds):
cols = ds["colors"]
for shp in slide.shapes:
if hasattr(shp, "text_frame"):
for p in shp.text_frame.paragraphs:
for r in p.runs:
r.font.name = ds["font"]
r.font.color.rgb = RGBColor.from_string(cols["text"][1:])
if shp == getattr(slide.shapes, "title", None):
r.font.color.rgb = RGBColor.from_string(cols["primary"][1:])
r.font.size = Pt(ds["title_size"]); r.font.bold=True
if ds["set_background"]:
slide.background.fill.solid();
slide.background.fill.fore_color.rgb = RGBColor.from_string(cols["background"][1:])
def enhance_slide(slide, prompt, ds):
orig = extract_slide_text(slide)
if not orig: return
frags = chunk_slide_text(orig, max_words=200)
enhanced_frags = []
for f in frags:
enhanced_frags.append(get_ai_response(f"\nImprove this:\n{f}\n\nInstructions: {prompt}"))
final = "\n".join(enhanced_frags)
title_sp = getattr(slide.shapes, "title", None)
for shp in list(slide.shapes):
if shp is not title_sp:
shp._element.getparent().remove(shp._element)
left, top = Inches(1), Inches(1.5 if title_sp else 0.5)
tb = slide.shapes.add_textbox(left, top, Inches(8), Inches(5))
tf = tb.text_frame; tf.word_wrap=True
apply_formatting(tf, final, ds)
apply_design(slide, ds)
def process_presentation(uploaded, prompt, ds):
with tempfile.NamedTemporaryFile(delete=False, suffix=".pptx") as tmp:
tmp.write(uploaded.read()); tmp_path=tmp.name
prs = Presentation(tmp_path)
for s in prs.slides:
enhance_slide(s, prompt, ds)
os.unlink(tmp_path)
return prs
# ── UI ─────────────────────────────────────────────────────────
st.title("Professional PPTX Enhancer")
uploaded = st.file_uploader("Upload PPTX", type=["pptx"])
user_prompt = st.text_area("Enhancement Instructions", placeholder="E.g. Improve clarity, add bullets", height=100)
with st.expander("🎨 Design Settings", True):
tpl = st.selectbox("Template", list(TEMPLATES.keys()))
if tpl=="Custom":
font = st.selectbox("Font", list(FONT_CHOICES))
ts = st.slider("Title size",12,60,32)
hs = st.slider("Heading size",12,48,24)
bs = st.slider("Body size",8,36,18)
sb = st.checkbox("Apply Background",True)
cols = {k:st.color_picker(k.capitalize(),c) for k,c in TEMPLATES["Office Default"]["colors"].items()}
else:
t = TEMPLATES[tpl]
font, ts, hs, bs, sb = t["font"], *t["sizes"].values(), t["background"]
cols = t["colors"]
ds = {
"font": FONT_CHOICES[font],
"colors": cols,
"title_size": ts,
"heading_size": hs,
"body_size": bs,
"set_background": sb
}
if st.button("Enhance Presentation") and uploaded and user_prompt:
out_prs = process_presentation(uploaded, user_prompt, ds)
buf = io.BytesIO(); out_prs.save(buf); buf.seek(0)
st.success("Done!")
st.download_button("Download Enhanced PPTX",
data=buf,
file_name="enhanced.pptx",
mime="application/vnd.openxmlformats-officedocument.presentationml.presentation")