# docloader **Repository Path**: jojobro/docloader ## Basic Information - **Project Name**: docloader - **Description**: 用于解析 txt,pdf,markdown 文件分块包 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-02-04 - **Last Updated**: 2026-02-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

DocLoader Logo

DocLoader

一个用于 RAG(检索增强生成)应用的 PHP 文档加载与分块工具库

PHP 8.1+ MIT License Tests PHPStan

安装基础使用进阶使用组件一览

--- ## 特性 - 🔥 支持多种文档格式:TXT、PDF、HTML、**Markdown** - 🌍 支持中英文混合文本分割 - ✂️ 智能分块策略,适配 RAG 向量化需求 - 📑 **Markdown 层级分块**,保留文档结构信息 - 🔧 高度可扩展,支持自定义 Reader 和 Splitter - 📦 零配置开箱即用 --- ## 安装 ```bash composer require catchadmin/docloader ``` ### 系统依赖 PDF 解析需要安装 **Poppler Utils**(pdftotext): | 系统 | 安装命令 | |-----|---------| | Ubuntu/Debian | `sudo apt-get install poppler-utils` | | CentOS/RHEL | `sudo yum install poppler-utils` | | macOS | `brew install poppler` | | Windows | [下载 Poppler](https://github.com/oschwartz10612/poppler-windows/releases) 并添加 `bin` 目录到 PATH | --- ## 基础使用 ### 从字符串加载 ```php use Catch\DocLoader\Loader\StringLoader; $documents = StringLoader::for('这是一段文本内容...') ->getDocuments(); // 设置来源名称 $documents = StringLoader::for('内容', 'my-document') ->getDocuments(); ``` ### 从文件加载 ```php use Catch\DocLoader\Loader\FileLoader; // 加载单个文件 $documents = FileLoader::for('/path/to/file.txt') ->getDocuments(); // 加载整个目录(递归) $documents = FileLoader::for('/path/to/documents/') ->getDocuments(); ``` ### 加载 PDF 文件 ```php use Catch\DocLoader\Loader\FileLoader; use Catch\DocLoader\Reader\PdfReader; $documents = FileLoader::for('/path/to/document.pdf') ->addReader('pdf', new PdfReader()) ->getDocuments(); ``` ### 自定义 pdftotext 路径 ```php // Windows 示例 $pdfReader = new PdfReader('C:\poppler\bin\pdftotext.exe'); $documents = FileLoader::for('/path/to/document.pdf') ->addReader('pdf', $pdfReader) ->getDocuments(); ``` ### 加载 HTML 文件 ```php use Catch\DocLoader\Loader\FileLoader; use Catch\DocLoader\Reader\HtmlReader; $documents = FileLoader::for('/path/to/page.html') ->addReader(['html', 'htm'], new HtmlReader()) ->getDocuments(); ``` ### 加载 Markdown 文件 ```php use Catch\DocLoader\Loader\FileLoader; use Catch\DocLoader\Reader\MarkdownReader; $documents = FileLoader::for('/path/to/document.md') ->addReader('md', new MarkdownReader()) ->getDocuments(); // 配置选项 $mdReader = new MarkdownReader( preserveHeadings: true, // 是否保留标题标记(默认 true) useGfm: true // 是否使用 GitHub Flavored Markdown(默认 true) ); $documents = FileLoader::for('/path/to/docs/') ->addReader('md', $mdReader) ->getDocuments(); ``` --- ## 进阶使用 ### 文本分块策略 #### DelimiterSplitter(分隔符分块) 按指定分隔符分割文本,适合结构化文档: ```php use Catch\DocLoader\Splitter\DelimiterSplitter; $splitter = new DelimiterSplitter( maxLength: 500, // 每块最大字符数 separator: "\n", // 分隔符(默认空格) wordOverlap: 20 // 词重叠数(保持上下文连贯) ); $documents = FileLoader::for($path) ->withSplitter($splitter) ->getDocuments(); ``` #### SentenceSplitter(句子分块)- 推荐用于 RAG 按句子边界分割,支持中英文,适合自然语言文档: ```php use Catch\DocLoader\Splitter\SentenceSplitter; $splitter = new SentenceSplitter( maxWords: 150, // 每块最大词数 overlapWords: 20 // 重叠词数 ); $documents = FileLoader::for($path) ->withSplitter($splitter) ->getDocuments(); ``` **RAG 推荐参数:** | 参数 | 推荐值 | 说明 | |-----|-------|------| | maxWords | 100-200 | 约 300-600 中文字符 | | overlapWords | 15-30 | 约 10-20% 重叠 | #### MarkdownSplitter(Markdown 层级分块)- 推荐用于知识库 按 Markdown 标题层级智能分块,保留文档结构信息: ```php use Catch\DocLoader\Splitter\MarkdownSplitter; $splitter = new MarkdownSplitter( maxLevel: 3, // 最深切分到 H3 minChunkSize: 50, // 最小块字符数 includeHeadingInContent: true // chunk 内容包含标题 ); $documents = FileLoader::for('/knowledge-base/') ->addReader('md', new MarkdownReader()) ->withSplitter($splitter) ->getDocuments(); ``` **分块示例:** ```markdown # 第一章 → Chunk1: {level:1, title:"第一章", path:["第一章"]} 内容... ## 1.1 节 → Chunk2: {level:2, title:"1.1 节", path:["第一章","1.1 节"], parentId:Chunk1.id} 内容... ### 1.1.1 小节 → Chunk3: {level:3, title:"1.1.1 小节", path:["第一章","1.1 节","1.1.1 小节"]} ``` **层级信息字段:** | 字段 | 类型 | 说明 | |-----|------|------| | `level` | int | 层级深度(0=无标题,1=H1,2=H2...) | | `sectionTitle` | string | 当前章节标题 | | `headingPath` | array | 完整标题路径 | | `parentId` | string | 父块 ID | ### 文件过滤 ```php $documents = FileLoader::for('/path/to/docs/') // 只处理指定扩展名 ->setIncludeExtensions(['pdf', 'txt', 'md']) // 排除匹配的文件/目录 ->setExcludePatterns(['*.tmp', '.git/*', 'node_modules/*']) ->addReader('pdf', new PdfReader()) ->getDocuments(); ``` ### 多格式混合加载 ```php $documents = FileLoader::for('/path/to/docs/') ->addReader('pdf', new PdfReader()) ->addReader(['html', 'htm'], new HtmlReader()) ->withSplitter(new SentenceSplitter(maxWords: 150, overlapWords: 20)) ->getDocuments(); ``` --- ## Document 对象 每个文档块包含以下属性: ```php $document->id; // 唯一 ID(自动生成) $document->content; // 文本内容 $document->sourceType; // 来源类型:'files', 'string' $document->sourceName; // 来源名称:文件名或自定义名称 $document->embedding; // 向量嵌入(默认空数组,由外部填充) $document->score; // 相关性分数(默认 0) $document->metadata; // 自定义元数据 ``` ### 操作 Document ```php // 链式设置 $document->setContent('新内容') ->setSourceName('custom-name') ->setMetadata(['author' => '张三', 'date' => '2024-01-01']) ->addMetadata('category', '技术文档'); // 序列化为 JSON $json = json_encode($document); ``` --- ## 自定义扩展 ### 自定义 Reader 实现 `ReaderInterface` 接口: ```php use Catch\DocLoader\Reader\ReaderInterface; class MarkdownReader implements ReaderInterface { public static function getText(string $filePath, array $options = []): string { $content = file_get_contents($filePath); // 处理 Markdown 语法... return $content; } public function read(string $filePath): string { return static::getText($filePath); } } // 使用 $documents = FileLoader::for('/docs/') ->addReader('md', new MarkdownReader()) ->getDocuments(); ``` ### 自定义 Splitter 继承 `AbstractSplitter`(推荐): ```php use Catch\DocLoader\Splitter\AbstractSplitter; use Catch\DocLoader\Document; class ParagraphSplitter extends AbstractSplitter { public function __construct( private int $minLength = 100 ) {} public function splitDocument(Document $document): array { $paragraphs = preg_split('/\n{2,}/', $document->getContent()); $result = []; foreach ($paragraphs as $para) { if (mb_strlen($para) >= $this->minLength) { $newDoc = new Document(trim($para)); $newDoc->sourceType = $document->getSourceType(); $newDoc->sourceName = $document->getSourceName(); $result[] = $newDoc; } } return $result; } } // 使用 $documents = FileLoader::for($path) ->withSplitter(new ParagraphSplitter(minLength: 50)) ->getDocuments(); ``` --- ## RAG 最佳实践 ### 推荐配置 ```php use Catch\DocLoader\Loader\FileLoader; use Catch\DocLoader\Reader\PdfReader; use Catch\DocLoader\Splitter\SentenceSplitter; $documents = FileLoader::for('/knowledge-base/') ->addReader('pdf', new PdfReader()) ->setIncludeExtensions(['pdf', 'txt', 'md']) ->setExcludePatterns(['*.tmp', '.*']) ->withSplitter(new SentenceSplitter( maxWords: 150, // 适合大多数 embedding 模型 overlapWords: 25 // 约 15% 重叠 )) ->getDocuments(); // 准备向量化 foreach ($documents as $doc) { $text = $doc->getContent(); // 调用 embedding API... // $embedding = $embeddingService->embed($text); // $doc->setEmbedding($embedding); } ``` ### 分块大小建议 | Embedding 模型 | maxWords | 说明 | |---------------|----------|------| | OpenAI text-embedding-3 | 150-200 | 支持 8191 tokens | | Cohere embed-v3 | 100-150 | 支持 512 tokens | | BGE-M3 | 200-300 | 支持 8192 tokens | --- ## 组件一览 ### Loader(加载器) | 类 | 说明 | |---|------| | `StringLoader` | 从字符串加载 | | `FileLoader` | 从文件或目录加载 | ### Reader(读取器) | 类 | 说明 | 依赖 | |---|------|------| | `TextFileReader` | 纯文本文件 | 无 | | `PdfReader` | PDF 文件 | pdftotext | | `HtmlReader` | HTML 文件 | html2text/html2text | | `MarkdownReader` | Markdown 文件 | league/commonmark | ### Splitter(分块器) | 类 | 说明 | 推荐场景 | |---|------|---------| | `DelimiterSplitter` | 按分隔符+最大长度 | 结构化文档 | | `SentenceSplitter` | 按句子+最大词数 | 自然语言文档(推荐) | | `MarkdownSplitter` | 按标题层级+保留结构 | Markdown 知识库(推荐) | --- ## License MIT License