Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 57 additions & 30 deletions openrag/components/indexer/loaders/pptx_loader.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
import html
import re
from io import BytesIO

import pptx
from html_to_markdown import convert
from langchain_core.documents.base import Document
from PIL import Image
from tqdm.asyncio import tqdm
from utils.logger import get_logger

from .base import BaseLoader

logger = get_logger()


class PPTXConverter:
"""Implementation based on PPTX converter in MarkItDown library.

https://github.com/microsoft/markitdown/blob/main/packages/markitdown/src/markitdown/converters/_pptx_converter.py
"""

def __init__(
self, image_placeholder=r"<image>", page_separator: str = "[PAGE_SEP]"
):
Expand Down Expand Up @@ -44,9 +54,7 @@ def convert(self, local_path):
html_table += "</tr>"
first_row = False
html_table += "</table></body></html>"
md_content += (
"\n" + self._convert(html_table).text_content.strip() + "\n"
)
md_content += "\n" + convert(html_table).text_content.strip() + "\n"

# Charts
if shape.has_chart:
Expand All @@ -73,40 +81,59 @@ def convert(self, local_path):
return md_content, images_list

def _is_picture(self, shape):
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.PICTURE:
return True
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.PLACEHOLDER:
if hasattr(shape, "image"):
try:
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.PICTURE:
return True
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.PLACEHOLDER:
if hasattr(shape, "image"):
return True
except NotImplementedError:
# https://python-pptx.readthedocs.io/en/latest/_modules/pptx/shapes/autoshape.html
# Not all shape types are implemented in python-pptx
logger.warning("Encountered an unimplemented shape type.")

return False

def _is_table(self, shape):
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.TABLE:
return True
try:
if shape.shape_type == pptx.enum.shapes.MSO_SHAPE_TYPE.TABLE:
return True
except NotImplementedError:
# # https://python-pptx.readthedocs.io/en/latest/_modules/pptx/shapes/autoshape.html
# Not all shape types are implemented in python-pptx
logger.warning("Encountered an unimplemented shape type.")
return False

def _convert_chart_to_markdown(self, chart):
md = "\n\n### Chart"
if chart.has_title:
md += f": {chart.chart_title.text_frame.text}"
md += "\n\n"
data = []
category_names = [c.label for c in chart.plots[0].categories]
series_names = [s.name for s in chart.series]
data.append(["Category"] + series_names)

for idx, category in enumerate(category_names):
row = [category]
for series in chart.series:
row.append(series.values[idx])
data.append(row)

markdown_table = []
for row in data:
markdown_table.append("| " + " | ".join(map(str, row)) + " |")
header = markdown_table[0]
separator = "|" + "|".join(["---"] * len(data[0])) + "|"
return md + "\n".join([header, separator] + markdown_table[1:])
try:
md = "\n\n### Chart"
if chart.has_title:
md += f": {chart.chart_title.text_frame.text}"
md += "\n\n"
data = []
category_names = [c.label for c in chart.plots[0].categories]
series_names = [s.name for s in chart.series]
data.append(["Category"] + series_names)

for idx, category in enumerate(category_names):
row = [category]
for series in chart.series:
row.append(series.values[idx])
data.append(row)

markdown_table = []
for row in data:
markdown_table.append("| " + " | ".join(map(str, row)) + " |")
header = markdown_table[0]
separator = "|" + "|".join(["---"] * len(data[0])) + "|"
return md + "\n".join([header, separator] + markdown_table[1:])
except ValueError as e:
# Handle the specific error for unsupported chart types
if "unsupported plot type" in str(e):
return "\n\n[unsupported chart]\n\n"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the handling of this exception is the same as the generic Exception, there is no point to have a specific ValueError exception, as I guess it inherits from Exception?

except Exception:
# Catch any other exceptions that might occur
return "\n\n[unsupported chart]\n\n"


class PPTXLoader(BaseLoader):
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ dependencies = [
"hdbscan>=0.8.40",
"pytest-env>=1.1.5",
"markitdown[docx]>=0.1.3",
"html-to-markdown>=2.4.0",
]

[dependency-groups]
Expand Down
15 changes: 15 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.