如何从目录加载文档
LangChain的DirectoryLoader实现了从磁盘读取文件到LangChain Document对象的功能。以下是演示内容:
如何从文件系统加载,包括使用通配符模式;
如何使用多线程进行文件I/O;
如何使用自定义加载器类来解析特定文件类型(例如代码);
如何处理错误,比如由于解码而导致的错误。
from langchain_community.document_loaders import DirectoryLoader
DirectoryLoader
接受一个loader_cls
关键字参数,默认为UnstructuredLoader。Unstructured支持解析多种格式,如PDF和HTML。这里我们用它来读取一个markdown(.md)文件。
我们可以使用glob
参数来控制加载哪些文件。请注意,这里不加载.rst
文件或.html
文件。
loader = DirectoryLoader("../", glob="**/*.md")
docs = loader.load()
len(docs)
20
print(docs[0].page_content[:100])
Security
LangChain has a large ecosystem of integrations with various external resources like local
显示进度条
默认情况下不会显示进度条。要显示进度条,请安装tqdm
库(例如pip install tqdm
),并将show_progress
参数设置为True
。
loader = DirectoryLoader("../", glob="**/*.md", show_progress=True)
docs = loader.load()
100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 20/20 [00:00<00:00, 54.56it/s]
使用多线程
默认情况下,加载在一个线程中进行。为了利用多个线程,将use_multithreading
标志设置为true。
loader = DirectoryLoader("../", glob="**/*.md", use_multithreading=True)
docs = loader.load()
更改加载器类
默认情况下使用UnstructuredLoader
类。要自定义加载器,请在loader_cls
关键字参数中指定加载器类。下面我们展示一个使用TextLoader的示例:
from langchain_community.document_loaders import TextLoader
loader = DirectoryLoader("../", glob="**/*.md", loader_cls=TextLoader)
docs = loader.load()
print(docs[0].page_content[:100])
# Security
LangChain has a large ecosystem of integrations with various external resources like loc
请注意,虽然UnstructuredLoader
解析Markdown标题,但TextLoader
不会。
如果需要加载Python源代码文件,请使用PythonLoader
:
from langchain_community.document_loaders import PythonLoader
loader = DirectoryLoader("../../../../../", glob="**/*.py", loader_cls=PythonLoader)
使用TextLoader自动检测文件编码
DirectoryLoader
可以帮助处理由文件编码变化引起的错误。下面我们将尝试加载一组文件,其中一个包含非UTF8编码。
path = "../../../../libs/langchain/tests/unit_tests/examples/"
loader = DirectoryLoader(path, glob="**/*.txt", loader_cls=TextLoader)
A. 默认行为
默认情况下会引发错误:
loader.load()
Error loading file ../../../../libs/langchain/tests/unit_tests/examples/example-non-utf8.txt
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
File ~/repos/langchain/libs/community/langchain_community/document_loaders/text.py:43, in TextLoader.lazy_load(self)
42 with open(self.file_path, encoding=self.encoding) as f:
---> 43 text = f.read()
File ~/.pyenv/versions/3.10.4/lib/python3.10/codecs.py:322, in BufferedIncrementalDecoder.decode(self, input, final)
321 data = self.buffer + input
--> 322 (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 0: invalid continuation byte
RuntimeError Traceback (most recent call last)
Cell In[10], line 1
----> 1 loader.load()
File ~/repos/langchain/libs/community/langchain_community/document_loaders/directory.py:117, in DirectoryLoader.load(self)
115 def load(self) -> List[Document]:
116 """Load documents."""
--> 117 return list(self.lazy_load())
File ~/repos/langchain/libs/community/langchain_community/document_loaders/directory.py:182, in DirectoryLoader.lazy_load(self)
180 else:
181 for i in items:
--> 182 yield from self._lazy_load_file(i, p, pbar)
File ~/repos/langchain/libs/community/langchain_community/document_loaders/directory.py:220, in DirectoryLoader._lazy_load_file(self, item, path, pbar)
218 else:
219 logger.error(f"Error loading file {str(item)}")
--> 220 raise e
File ~/repos/langchain/libs/community/langchain_community/document_loaders/directory.py:210, in DirectoryLoader._lazy_load_file(self, item, path, pbar)
208 loader = self.loader_cls(str(item), **self.loader_kwargs)
209 try:
--> 210 for subdoc in loader.lazy_load():
211 yield subdoc
212 except NotImplementedError:
File ~/repos/langchain/libs/community/langchain_community/document_loaders/text.py:56, in TextLoader.lazy_load(self)
54 continue
55 else:
---> 56 raise RuntimeError(f"Error loading {self.file_path}") from e
57 except Exception as e:
58 raise RuntimeError(f"Error loading {self.file_path}") from e
RuntimeError: Error loading ../../../../libs/langchain/tests/unit_tests/examples/example-non-utf8.txt
文件 example-non-utf8.txt
使用了不同的编码,因此 load()
函数会失败,并显示一条有用的消息,指出哪个文件解码失败了。
使用 TextLoader
的默认行为,如果加载文档失败,整个加载过程将失败,没有任何文档被加载。
B. 静默失败
我们可以向 DirectoryLoader
传递参数 silent_errors
,以跳过无法加载的文件并继续加载过程。
loader = DirectoryLoader(
path, glob="**/*.txt", loader_cls=TextLoader, silent_errors=True
)
docs = loader.load()
Error loading file ../../../../libs/langchain/tests/unit_tests/examples/example-non-utf8.txt: Error loading ../../../../libs/langchain/tests/unit_tests/examples/example-non-utf8.txt
doc_sources = [doc.metadata["source"] for doc in docs]
doc_sources
['../../../../libs/langchain/tests/unit_tests/examples/example-utf8.txt']
C. 自动检测编码
我们还可以要求 TextLoader
在失败之前自动检测文件编码,通过向加载器类传递 autodetect_encoding
参数。
text_loader_kwargs = {"autodetect_encoding": True}
loader = DirectoryLoader(
path, glob="**/*.txt", loader_cls=TextLoader, loader_kwargs=text_loader_kwargs
)
docs = loader.load()
doc_sources = [doc.metadata["source"] for doc in docs]
doc_sources
['../../../../libs/langchain/tests/unit_tests/examples/example-utf8.txt',
'../../../../libs/langchain/tests/unit_tests/examples/example-non-utf8.txt']