Skip to content

Commit a6f2d61

Browse files
Add a PDF Loader node and explicit PDF support for LoadText (#93)
* pdf loader * update to use pdfminer * back to pypdf
1 parent 1dbf0e7 commit a6f2d61

4 files changed

Lines changed: 110 additions & 2 deletions

File tree

griptape_nodes_library.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2711,6 +2711,17 @@
27112711
"icon": "Combine"
27122712
}
27132713
},
2714+
{
2715+
"class_name": "LoadPdf",
2716+
"file_path": "griptape_nodes_library/files/load_pdf.py",
2717+
"metadata": {
2718+
"category": "files",
2719+
"description": "Load a local PDF file and extract its text content, with outputs for the full joined text, a per-page list, and page count.",
2720+
"display_name": "Load PDF",
2721+
"icon": "file-text",
2722+
"group": "Input/Output"
2723+
}
2724+
},
27142725
{
27152726
"class_name": "PathAddExtension",
27162727
"file_path": "griptape_nodes_library/files/path_add_extension.py",
@@ -2840,4 +2851,4 @@
28402851
"workflows/templates/rodin_3d_-_3d_model_from_image.py"
28412852
],
28422853
"is_default_library": true
2843-
}
2854+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
from typing import Any
2+
3+
from griptape.loaders import PdfLoader
4+
from griptape_nodes.exe_types.core_types import Parameter, ParameterMode
5+
from griptape_nodes.exe_types.node_types import ControlNode
6+
from griptape_nodes.traits.file_system_picker import FileSystemPicker
7+
8+
9+
class LoadPdf(ControlNode):
10+
def __init__(
11+
self,
12+
name: str,
13+
metadata: dict[Any, Any] | None = None,
14+
) -> None:
15+
super().__init__(name, metadata)
16+
17+
self.path = Parameter(
18+
name="path",
19+
allowed_modes={ParameterMode.INPUT, ParameterMode.PROPERTY},
20+
input_types=["str"],
21+
type="str",
22+
default_value="",
23+
tooltip="Path to the local PDF file to load.",
24+
)
25+
self.path.add_trait(
26+
FileSystemPicker(
27+
allow_files=True,
28+
allow_directories=False,
29+
multiple=False,
30+
file_types=[".pdf"],
31+
)
32+
)
33+
self.add_parameter(self.path)
34+
35+
self.add_parameter(
36+
Parameter(
37+
name="password",
38+
allowed_modes={ParameterMode.INPUT, ParameterMode.PROPERTY},
39+
input_types=["str"],
40+
type="str",
41+
default_value="",
42+
tooltip="Optional password for password-protected PDFs. Leave blank if not needed.",
43+
)
44+
)
45+
46+
self.add_parameter(
47+
Parameter(
48+
name="text",
49+
allowed_modes={ParameterMode.OUTPUT},
50+
output_type="str",
51+
default_value="",
52+
tooltip="The full text content of the PDF, with all pages joined by two newlines.",
53+
ui_options={"multiline": True, "placeholder_text": "PDF text will appear here."},
54+
)
55+
)
56+
57+
self.add_parameter(
58+
Parameter(
59+
name="pages",
60+
allowed_modes={ParameterMode.OUTPUT},
61+
output_type="list",
62+
default_value=[],
63+
tooltip="A list of strings, one entry per page of the PDF, in order.",
64+
)
65+
)
66+
67+
self.add_parameter(
68+
Parameter(
69+
name="page_count",
70+
allowed_modes={ParameterMode.OUTPUT},
71+
output_type="int",
72+
default_value=0,
73+
tooltip="The total number of pages in the PDF.",
74+
)
75+
)
76+
77+
def process(self) -> None:
78+
path = self.get_parameter_value("path")
79+
password = self.get_parameter_value("password") or ""
80+
81+
loader = PdfLoader()
82+
data = loader.fetch(path)
83+
pages_artifact = loader.try_parse(data, password=password or None)
84+
page_texts = [page.value for page in pages_artifact]
85+
86+
full_text = "\n\n".join(page_texts)
87+
page_count = len(page_texts)
88+
89+
self.parameter_output_values["text"] = full_text
90+
self.parameter_output_values["pages"] = page_texts
91+
self.parameter_output_values["page_count"] = page_count
92+
93+
self.parameter_values["text"] = full_text
94+
self.parameter_values["pages"] = page_texts
95+
self.parameter_values["page_count"] = page_count

griptape_nodes_library/text/load_text.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ def process(self) -> None:
5656
# Load file content based on extension
5757
ext = os.path.splitext(text_path)[1] # noqa: PTH122
5858
if ext.lower() == ".pdf":
59-
output_text = PdfLoader().load(text_path)[0].value
59+
pages_artifact = PdfLoader().load(text_path)
60+
output_text = "\n\n".join(page.value for page in pages_artifact)
6061
else:
6162
output_text = File(text_path).read_text()
6263

griptape_nodes_library/utils/file_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
".xml",
1414
".env",
1515
".py",
16+
".pdf",
1617
}
1718

1819

0 commit comments

Comments
 (0)