diff --git a/docs/modules/indexes/document_loaders/examples/example_data/fake.odt b/docs/modules/indexes/document_loaders/examples/example_data/fake.odt new file mode 100644 index 000000000..905049972 Binary files /dev/null and b/docs/modules/indexes/document_loaders/examples/example_data/fake.odt differ diff --git a/docs/modules/indexes/document_loaders/examples/odt.ipynb b/docs/modules/indexes/document_loaders/examples/odt.ipynb new file mode 100644 index 000000000..9bdee7aa3 --- /dev/null +++ b/docs/modules/indexes/document_loaders/examples/odt.ipynb @@ -0,0 +1,76 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "22a849cc", + "metadata": {}, + "source": [ + "## Unstructured ODT Loader\n", + "\n", + "The `UnstructuredODTLoader` can be used to load Open Office ODT files." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "e6616e3a", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain.document_loaders import UnstructuredODTLoader" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "a654e4d9", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Document(page_content='Lorem ipsum dolor sit amet.', metadata={'source': 'example_data/fake.odt', 'filename': 'example_data/fake.odt', 'category': 'Title'})" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "loader = UnstructuredODTLoader(\"example_data/fake.odt\", mode=\"elements\")\n", + "docs = loader.load()\n", + "docs[0]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9ab94bde", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/langchain/document_loaders/__init__.py b/langchain/document_loaders/__init__.py index f2ff3d9c7..d408add31 100644 --- a/langchain/document_loaders/__init__.py +++ b/langchain/document_loaders/__init__.py @@ -53,6 +53,7 @@ from langchain.document_loaders.notebook import NotebookLoader from langchain.document_loaders.notion import NotionDirectoryLoader from langchain.document_loaders.notiondb import NotionDBLoader from langchain.document_loaders.obsidian import ObsidianLoader +from langchain.document_loaders.odt import UnstructuredODTLoader from langchain.document_loaders.onedrive import OneDriveLoader from langchain.document_loaders.pdf import ( MathpixPDFLoader, @@ -190,6 +191,7 @@ __all__ = [ "UnstructuredHTMLLoader", "UnstructuredImageLoader", "UnstructuredMarkdownLoader", + "UnstructuredODTLoader", "UnstructuredPDFLoader", "UnstructuredPowerPointLoader", "UnstructuredRTFLoader", diff --git a/langchain/document_loaders/odt.py b/langchain/document_loaders/odt.py new file mode 100644 index 000000000..b8eedb314 --- /dev/null +++ b/langchain/document_loaders/odt.py @@ -0,0 +1,22 @@ +"""Loader that loads Open Office ODT files.""" +from typing import Any, List + +from langchain.document_loaders.unstructured import ( + UnstructuredFileLoader, + validate_unstructured_version, +) + + +class UnstructuredODTLoader(UnstructuredFileLoader): + """Loader that uses unstructured to load open office ODT files.""" + + def __init__( + self, file_path: str, mode: str = "single", **unstructured_kwargs: Any + ): + validate_unstructured_version(min_unstructured_version="0.6.3") + super().__init__(file_path=file_path, mode=mode, **unstructured_kwargs) + + def _get_elements(self) -> List: + from unstructured.partition.odt import partition_odt + + return partition_odt(filename=self.file_path, **self.unstructured_kwargs) diff --git a/langchain/document_loaders/unstructured.py b/langchain/document_loaders/unstructured.py index 83fccbf19..276c8551a 100644 --- a/langchain/document_loaders/unstructured.py +++ b/langchain/document_loaders/unstructured.py @@ -23,6 +23,15 @@ def satisfies_min_unstructured_version(min_version: str) -> bool: return unstructured_version_tuple >= min_version_tuple +def validate_unstructured_version(min_unstructured_version: str) -> None: + """Raises an error if the unstructured version does not exceed the + specified minimum.""" + if not satisfies_min_unstructured_version(min_unstructured_version): + raise ValueError( + f"unstructured>={min_unstructured_version} is required in this loader." + ) + + class UnstructuredBaseLoader(BaseLoader, ABC): """Loader that uses unstructured to load files.""" diff --git a/tests/integration_tests/document_loaders/test_odt.py b/tests/integration_tests/document_loaders/test_odt.py new file mode 100644 index 000000000..0aa833ceb --- /dev/null +++ b/tests/integration_tests/document_loaders/test_odt.py @@ -0,0 +1,12 @@ +from pathlib import Path + +from langchain.document_loaders import UnstructuredODTLoader + + +def test_unstructured_odt_loader() -> None: + """Test unstructured loader.""" + file_path = Path(__file__).parent.parent / "examples/fake.odt" + loader = UnstructuredODTLoader(str(file_path)) + docs = loader.load() + + assert len(docs) == 1 diff --git a/tests/integration_tests/examples/fake.odt b/tests/integration_tests/examples/fake.odt new file mode 100644 index 000000000..905049972 Binary files /dev/null and b/tests/integration_tests/examples/fake.odt differ