Medilingua-space / src /pdf_utils.py
param2004's picture
Upload 17 files
690bcb6 verified
import io
from typing import List, Dict
import streamlit as st
def _import_reportlab():
try:
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import mm
from reportlab.pdfgen import canvas
from reportlab.platypus import Paragraph, SimpleDocTemplate, Spacer, Table, TableStyle
from reportlab.lib import colors
return {
"A4": A4,
"getSampleStyleSheet": getSampleStyleSheet,
"mm": mm,
"canvas": canvas,
"Paragraph": Paragraph,
"SimpleDocTemplate": SimpleDocTemplate,
"Spacer": Spacer,
"Table": Table,
"TableStyle": TableStyle,
"colors": colors,
}
except Exception:
return None
def build_chat_pdf(messages: List[Dict[str, str]], title: str = "MediLingua Chat Transcript") -> io.BytesIO:
"""
Create a PDF from chat messages and return as an in-memory BytesIO buffer.
Each message is a dict with keys: role ('user'|'assistant'), content (str).
"""
libs = _import_reportlab()
if libs is None:
st.error(
"PDF generation library not found. Install with: `pip install reportlab` and rerun."
)
return None
buffer = io.BytesIO()
doc = libs["SimpleDocTemplate"](buffer, pagesize=libs["A4"], rightMargin=28, leftMargin=28, topMargin=36, bottomMargin=28)
styles = libs["getSampleStyleSheet"]()
elements = []
# Title
title_style = styles["Title"]
elements.append(libs["Paragraph"](title, title_style))
elements.append(libs["Spacer"](1, 12))
# Build a table-like layout for messages
data = []
table_style_cmds = [
("VALIGN", (0, 0), (-1, -1), "TOP"),
("INNERGRID", (0, 0), (-1, -1), 0.25, libs["colors"].lightgrey),
("BOX", (0, 0), (-1, -1), 0.25, libs["colors"].lightgrey),
("LEFTPADDING", (0, 0), (-1, -1), 6),
("RIGHTPADDING", (0, 0), (-1, -1), 6),
("TOPPADDING", (0, 0), (-1, -1), 6),
("BOTTOMPADDING", (0, 0), (-1, -1), 6),
]
role_style = styles["Heading5"]
body_style = styles["BodyText"]
for msg in messages:
role = msg.get("role", "").capitalize()
content = msg.get("content", "")
# Left column: role, Right column: content paragraph
role_par = libs["Paragraph"](f"<b>{role}</b>", role_style)
content_par = libs["Paragraph"](content.replace("\n", "<br/>"), body_style)
data.append([role_par, content_par])
table = libs["Table"](data, colWidths=[30 * libs["mm"], None])
table.setStyle(libs["TableStyle"](table_style_cmds))
elements.append(table)
doc.build(elements)
buffer.seek(0)
return buffer