mirror of
https://github.com/microsoft/autogen.git
synced 2025-09-13 18:25:42 +00:00
129 lines
4.2 KiB
Python
129 lines
4.2 KiB
Python
![]() |
import unicodedata
|
||
|
import uuid
|
||
|
from io import BytesIO
|
||
|
from pathlib import Path
|
||
|
from typing import Dict, List, Optional
|
||
|
|
||
|
import requests
|
||
|
from autogen_core.code_executor import ImportFromModule
|
||
|
from autogen_core.tools import FunctionTool
|
||
|
from fpdf import FPDF
|
||
|
from PIL import Image, ImageDraw, ImageOps
|
||
|
|
||
|
|
||
|
async def generate_pdf(
|
||
|
sections: List[Dict[str, Optional[str]]], output_file: str = "report.pdf", report_title: str = "PDF Report"
|
||
|
) -> str:
|
||
|
"""
|
||
|
Generate a PDF report with formatted sections including text and images.
|
||
|
|
||
|
Args:
|
||
|
sections: List of dictionaries containing section details with keys:
|
||
|
- title: Section title
|
||
|
- level: Heading level (title, h1, h2)
|
||
|
- content: Section text content
|
||
|
- image: Optional image URL or file path
|
||
|
output_file: Name of output PDF file
|
||
|
report_title: Title shown at top of report
|
||
|
|
||
|
Returns:
|
||
|
str: Path to the generated PDF file
|
||
|
"""
|
||
|
|
||
|
def normalize_text(text: str) -> str:
|
||
|
"""Normalize Unicode text to ASCII."""
|
||
|
return unicodedata.normalize("NFKD", text).encode("ascii", "ignore").decode("ascii")
|
||
|
|
||
|
def get_image(image_url_or_path):
|
||
|
"""Fetch image from URL or local path."""
|
||
|
if image_url_or_path.startswith(("http://", "https://")):
|
||
|
response = requests.get(image_url_or_path)
|
||
|
if response.status_code == 200:
|
||
|
return BytesIO(response.content)
|
||
|
elif Path(image_url_or_path).is_file():
|
||
|
return open(image_url_or_path, "rb")
|
||
|
return None
|
||
|
|
||
|
def add_rounded_corners(img, radius=6):
|
||
|
"""Add rounded corners to an image."""
|
||
|
mask = Image.new("L", img.size, 0)
|
||
|
draw = ImageDraw.Draw(mask)
|
||
|
draw.rounded_rectangle([(0, 0), img.size], radius, fill=255)
|
||
|
img = ImageOps.fit(img, mask.size, centering=(0.5, 0.5))
|
||
|
img.putalpha(mask)
|
||
|
return img
|
||
|
|
||
|
class PDF(FPDF):
|
||
|
"""Custom PDF class with header and content formatting."""
|
||
|
|
||
|
def header(self):
|
||
|
self.set_font("Arial", "B", 12)
|
||
|
normalized_title = normalize_text(report_title)
|
||
|
self.cell(0, 10, normalized_title, 0, 1, "C")
|
||
|
|
||
|
def chapter_title(self, txt):
|
||
|
self.set_font("Arial", "B", 12)
|
||
|
normalized_txt = normalize_text(txt)
|
||
|
self.cell(0, 10, normalized_txt, 0, 1, "L")
|
||
|
self.ln(2)
|
||
|
|
||
|
def chapter_body(self, body):
|
||
|
self.set_font("Arial", "", 12)
|
||
|
normalized_body = normalize_text(body)
|
||
|
self.multi_cell(0, 10, normalized_body)
|
||
|
self.ln()
|
||
|
|
||
|
def add_image(self, img_data):
|
||
|
img = Image.open(img_data)
|
||
|
img = add_rounded_corners(img)
|
||
|
img_path = Path(f"temp_{uuid.uuid4().hex}.png")
|
||
|
img.save(img_path, format="PNG")
|
||
|
self.image(str(img_path), x=None, y=None, w=190 if img.width > 190 else img.width)
|
||
|
self.ln(10)
|
||
|
img_path.unlink()
|
||
|
|
||
|
# Initialize PDF
|
||
|
pdf = PDF()
|
||
|
pdf.add_page()
|
||
|
font_size = {"title": 16, "h1": 14, "h2": 12, "body": 12}
|
||
|
|
||
|
# Add sections
|
||
|
for section in sections:
|
||
|
title = section.get("title", "")
|
||
|
level = section.get("level", "h1")
|
||
|
content = section.get("content", "")
|
||
|
image = section.get("image")
|
||
|
|
||
|
pdf.set_font("Arial", "B" if level in font_size else "", font_size.get(level, font_size["body"]))
|
||
|
pdf.chapter_title(title)
|
||
|
|
||
|
if content:
|
||
|
pdf.chapter_body(content)
|
||
|
|
||
|
if image:
|
||
|
img_data = get_image(image)
|
||
|
if img_data:
|
||
|
pdf.add_image(img_data)
|
||
|
if isinstance(img_data, BytesIO):
|
||
|
img_data.close()
|
||
|
|
||
|
pdf.output(output_file)
|
||
|
return output_file
|
||
|
|
||
|
|
||
|
# Create the PDF generation tool
|
||
|
generate_pdf_tool = FunctionTool(
|
||
|
func=generate_pdf,
|
||
|
description="Generate PDF reports with formatted sections containing text and images",
|
||
|
global_imports=[
|
||
|
"uuid",
|
||
|
"requests",
|
||
|
"unicodedata",
|
||
|
ImportFromModule("typing", ("List", "Dict", "Optional")),
|
||
|
ImportFromModule("pathlib", ("Path",)),
|
||
|
ImportFromModule("fpdf", ("FPDF",)),
|
||
|
ImportFromModule("PIL", ("Image", "ImageDraw", "ImageOps")),
|
||
|
ImportFromModule("io", ("BytesIO",)),
|
||
|
],
|
||
|
)
|