如何从目录加载文档 
LangChain 的DirectoryLoader实现了从磁盘读取文件到 LangChain Document对象的功能。以下是演示内容:
- 如何从文件系统加载,包括使用通配符模式; 
- 如何使用多线程进行文件 I/O; 
- 如何使用自定义加载器类来解析特定文件类型(例如代码); 
- 如何处理错误,比如由于解码而导致的错误。 
from langchain_community.document_loaders import DirectoryLoaderDirectoryLoader接受一个loader_cls关键字参数,默认为UnstructuredLoader。Unstructured支持解析多种格式,如 PDF 和 HTML。这里我们用它来读取一个 markdown(.md)文件。
我们可以使用glob参数来控制加载哪些文件。请注意,这里不加载.rst文件或.html文件。
loader = DirectoryLoader("../", glob="**/*.md")
docs = loader.load()
len(docs)20print(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.txtdoc_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']