from langchain_core.prompts import ChatPromptTemplate from llm_factory import get_llm from fpdf import FPDF import qrcode import os llm = get_llm(model_type="text", temperature=0.1) system_prompt = """You are a Medical Report Generator. Based on the diagnosis and action plan, write a formal medical report. Include: 1. Patient Summary. 2. Clinical Findings. 3. Diagnosis. 4. Recommendations & Prescription. 5. A polite closing. Format it as a clean text that can be put into a PDF. """ prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), ("user", "Patient: {patient_info}\nDiagnosis: {diagnosis}\nPlan: {plan}") ]) chain = prompt | llm async def generate_report_content(patient_info: dict, diagnosis: str, plan: str) -> str: response = await chain.ainvoke({ "patient_info": str(patient_info), "diagnosis": diagnosis, "plan": plan }) return response.content def create_pdf_report(content: str, patient_name: str, filename: str = "report.pdf"): pdf = FPDF() pdf.add_page() pdf.set_font("Arial", size=12) # Header pdf.set_font("Arial", 'B', 16) pdf.cell(200, 10, txt="Medical Report", ln=1, align='C') pdf.set_font("Arial", size=12) pdf.cell(200, 10, txt="Dr. Amine Tounsi", ln=1, align='C') pdf.ln(10) # Content # Sanitize content for FPDF (latin-1) replacements = { "\u2019": "'", # Smart quote "\u2018": "'", "\u201c": '"', # Smart double quotes "\u201d": '"', "\u2013": "-", # En dash "\u2014": "-", # Em dash "\u2264": "<=", # Less than or equal "\u2265": ">=", # Greater than or equal "…": "...", "–": "-" } for char, replacement in replacements.items(): content = content.replace(char, replacement) # Final fallback: encode to latin-1, replace errors with '?', then decode content = content.encode('latin-1', 'replace').decode('latin-1') pdf.multi_cell(0, 10, txt=content) # QR Code qr = qrcode.QRCode(version=1, box_size=10, border=5) qr.add_data(f"Patient: {patient_name} - Verified by Dr. Tounsi") qr.make(fit=True) img = qr.make_image(fill_color="black", back_color="white") img.save("temp_qr.png") pdf.ln(10) pdf.image("temp_qr.png", w=30) os.remove("temp_qr.png") # Ensure directory exists os.makedirs("reports", exist_ok=True) pdf.output(f"reports/{filename}") return f"reports/{filename}"