multi-ocr-py 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. multi_ocr_py-0.1.0/.gitignore +179 -0
  2. multi_ocr_py-0.1.0/.python-version +1 -0
  3. multi_ocr_py-0.1.0/LICENSE +21 -0
  4. multi_ocr_py-0.1.0/PKG-INFO +129 -0
  5. multi_ocr_py-0.1.0/README.md +103 -0
  6. multi_ocr_py-0.1.0/docs/liteparse/Markdown-Output.md +101 -0
  7. multi_ocr_py-0.1.0/docs/liteparse/library-use.md +439 -0
  8. multi_ocr_py-0.1.0/docs/liteparse/ocr-config.md +200 -0
  9. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-batch-pdf-concurrency-design.md +65 -0
  10. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-batch-processing-design.md +128 -0
  11. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-cli-args-design.md +149 -0
  12. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-concurrency-design.md +127 -0
  13. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-engine-refactor-design.md +210 -0
  14. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-liteparse-engine-design.md +144 -0
  15. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-model-shorthand-design.md +113 -0
  16. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-multi-ocr-design.md +155 -0
  17. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-ollama-engine-design.md +67 -0
  18. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-15-pdf-progress-design.md +73 -0
  19. multi_ocr_py-0.1.0/docs/superpowers/specs/2026-07-16-src-package-restructure-design.md +115 -0
  20. multi_ocr_py-0.1.0/pyproject.toml +51 -0
  21. multi_ocr_py-0.1.0/src/multi_ocr/__init__.py +25 -0
  22. multi_ocr_py-0.1.0/src/multi_ocr/batch.py +139 -0
  23. multi_ocr_py-0.1.0/src/multi_ocr/cli.py +206 -0
  24. multi_ocr_py-0.1.0/src/multi_ocr/engines/__init__.py +49 -0
  25. multi_ocr_py-0.1.0/src/multi_ocr/engines/base.py +94 -0
  26. multi_ocr_py-0.1.0/src/multi_ocr/engines/dashscope.py +85 -0
  27. multi_ocr_py-0.1.0/src/multi_ocr/engines/liteparse.py +60 -0
  28. multi_ocr_py-0.1.0/src/multi_ocr/engines/ollama.py +61 -0
  29. multi_ocr_py-0.1.0/src/multi_ocr/engines/siliconflow.py +80 -0
  30. multi_ocr_py-0.1.0/src/multi_ocr/pdf_utils.py +146 -0
  31. multi_ocr_py-0.1.0/src/multi_ocr/single.py +91 -0
  32. multi_ocr_py-0.1.0/tests/1.jpg +0 -0
  33. multi_ocr_py-0.1.0/tests/2.pdf +0 -0
  34. multi_ocr_py-0.1.0/tests/conftest.py +38 -0
  35. multi_ocr_py-0.1.0/tests/test_batch.py +374 -0
  36. multi_ocr_py-0.1.0/tests/test_engines.py +127 -0
  37. multi_ocr_py-0.1.0/tests/test_pdf_utils.py +190 -0
  38. multi_ocr_py-0.1.0/tests/test_single.py +127 -0
  39. multi_ocr_py-0.1.0/uv.lock +513 -0
@@ -0,0 +1,179 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ ### Python ###
13
+ # Byte-compiled / optimized / DLL files
14
+ __pycache__/
15
+ *.py[cod]
16
+ *$py.class
17
+
18
+ # C extensions
19
+ *.so
20
+
21
+ # Distribution / packaging
22
+ .Python
23
+ build/
24
+ develop-eggs/
25
+ dist/
26
+ downloads/
27
+ eggs/
28
+ .eggs/
29
+ lib/
30
+ lib64/
31
+ parts/
32
+ sdist/
33
+ var/
34
+ wheels/
35
+ share/python-wheels/
36
+ *.egg-info/
37
+ .installed.cfg
38
+ *.egg
39
+ MANIFEST
40
+
41
+ # PyInstaller
42
+ # Usually these files are written by a python script from a template
43
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
44
+ *.manifest
45
+ *.spec
46
+
47
+ # Installer logs
48
+ pip-log.txt
49
+ pip-delete-this-directory.txt
50
+
51
+ # Unit test / coverage reports
52
+ htmlcov/
53
+ .tox/
54
+ .nox/
55
+ .coverage
56
+ .coverage.*
57
+ .cache
58
+ nosetests.xml
59
+ coverage.xml
60
+ *.cover
61
+ *.py,cover
62
+ .hypothesis/
63
+ .pytest_cache/
64
+ cover/
65
+
66
+ # Translations
67
+ *.mo
68
+ *.pot
69
+
70
+ # Django stuff:
71
+ *.log
72
+ local_settings.py
73
+ db.sqlite3
74
+ db.sqlite3-journal
75
+
76
+ # Flask stuff:
77
+ instance/
78
+ .webassets-cache
79
+
80
+ # Scrapy stuff:
81
+ .scrapy
82
+
83
+ # Sphinx documentation
84
+ docs/_build/
85
+
86
+ # PyBuilder
87
+ .pybuilder/
88
+ target/
89
+
90
+ # Jupyter Notebook
91
+ .ipynb_checkpoints
92
+
93
+ # IPython
94
+ profile_default/
95
+ ipython_config.py
96
+
97
+ # pyenv
98
+ # For a library or package, you might want to ignore these files since the code is
99
+ # intended to run in multiple environments; otherwise, check them in:
100
+ # .python-version
101
+
102
+ # pipenv
103
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
104
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
105
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
106
+ # install all needed dependencies.
107
+ #Pipfile.lock
108
+
109
+ # poetry
110
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
111
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
112
+ # commonly ignored for libraries.
113
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
114
+ #poetry.lock
115
+
116
+ # pdm
117
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
118
+ #pdm.lock
119
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
120
+ # in version control.
121
+ # https://pdm.fming.dev/#use-with-ide
122
+ .pdm.toml
123
+
124
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
125
+ __pypackages__/
126
+
127
+ # Celery stuff
128
+ celerybeat-schedule
129
+ celerybeat.pid
130
+
131
+ # SageMath parsed files
132
+ *.sage.py
133
+
134
+ # Environments
135
+ .env
136
+ .venv
137
+ env/
138
+ venv/
139
+ ENV/
140
+ env.bak/
141
+ venv.bak/
142
+
143
+ # Spyder project settings
144
+ .spyderproject
145
+ .spyproject
146
+
147
+ # Rope project settings
148
+ .ropeproject
149
+
150
+ # mkdocs documentation
151
+ /site
152
+
153
+ # mypy
154
+ .mypy_cache/
155
+ .dmypy.json
156
+ dmypy.json
157
+
158
+ # Pyre type checker
159
+ .pyre/
160
+
161
+ # pytype static type analyzer
162
+ .pytype/
163
+
164
+ # Cython debug symbols
165
+ cython_debug/
166
+
167
+ # PyCharm
168
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
169
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
170
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
171
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
172
+ #.idea/
173
+ tests/1.txt
174
+ tests/2.txt
175
+ tests/1.md
176
+ tests/2.md
177
+ tests/3.md
178
+ temp
179
+ .DS_Store
@@ -0,0 +1 @@
1
+ 3.11
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yinnan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,129 @@
1
+ Metadata-Version: 2.4
2
+ Name: multi-ocr-py
3
+ Version: 0.1.0
4
+ Summary: 多引擎 OCR 工具包:将 PDF 和图片转换为 Markdown,支持 CLI 全局安装和 SDK 依赖两种使用方式
5
+ Project-URL: Repository, https://github.com/BlackBoxRecorder/multi-ocr
6
+ Author-email: Yinnan <im.yinnan@outlook.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: cli,markdown,ocr,pdf,vision-language-model
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
18
+ Classifier: Topic :: Text Processing :: Markup :: Markdown
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: liteparse
21
+ Requires-Dist: ollama
22
+ Requires-Dist: openai>=2.45.0
23
+ Requires-Dist: pymupdf>=1.28.0
24
+ Requires-Dist: tqdm>=4.67.0
25
+ Description-Content-Type: text/markdown
26
+
27
+ # multi-ocr
28
+
29
+ 多引擎 OCR 工具包,将 PDF 和图片转换为 Markdown 文档。
30
+
31
+ - **CLI 工具**:全局安装后一行命令完成 OCR
32
+ - **SDK 依赖**:作为 Python 库集成到你的项目中
33
+
34
+ ## 支持的引擎
35
+
36
+ | 引擎 | 说明 | 类型 |
37
+ |---|---|---|
38
+ | SiliconFlow + DeepSeek-OCR | 云端 OCR,精度高 | API |
39
+ | SiliconFlow + PaddleOCR-VL-1.5 | 云端 OCR,轻量快速 | API |
40
+ | DashScope + Qwen-VL-OCR | 阿里云百炼 | API |
41
+ | LiteParse | 本地 PDF 解析,无需联网 | 本地 |
42
+ | Ollama + DeepSeek-OCR | 本地部署 OCR | 本地 |
43
+
44
+ ## 安装
45
+
46
+ ### CLI 全局安装
47
+
48
+ ```bash
49
+ uv tool install multi-ocr
50
+ # 或
51
+ pip install multi-ocr
52
+ ```
53
+
54
+ ### SDK 依赖安装
55
+
56
+ ```bash
57
+ pip install multi-ocr
58
+ # 或
59
+ uv add multi-ocr
60
+ ```
61
+
62
+ ## CLI 使用
63
+
64
+ ```bash
65
+ # 单文件 OCR
66
+ multi-ocr document.pdf
67
+
68
+ # 指定引擎和页码范围
69
+ multi-ocr document.pdf --model dashscope-qwen-vl-ocr --pages 1-5
70
+
71
+ # 批量处理目录
72
+ multi-ocr ./scans/ --model silicon-deepseek-ocr -j 4
73
+
74
+ # 查看帮助
75
+ multi-ocr --help
76
+ ```
77
+
78
+ ### 环境变量
79
+
80
+ | 引擎 | 环境变量 |
81
+ |---|---|
82
+ | SiliconFlow | `SILICONFLOW_API_KEY` |
83
+ | DashScope | `DASHSCOPE_API_KEY` |
84
+ | Ollama | `OLLAMA_BASE_URL`(可选,默认 http://127.0.0.1:11434)|
85
+
86
+ 也可通过 `--api-key` 参数直接传入。
87
+
88
+ ## SDK 使用
89
+
90
+ ```python
91
+ from pathlib import Path
92
+ from multi_ocr import get_engine, ocr_file, OCREngine
93
+
94
+ # 创建引擎
95
+ engine = get_engine(
96
+ provider="siliconflow",
97
+ model="deepseek-ai/DeepSeek-OCR",
98
+ api_key="your-api-key",
99
+ )
100
+
101
+ # 识别图片
102
+ text = engine.parse_image(Path("scan.jpg"))
103
+
104
+ # 识别 PDF
105
+ result = ocr_file(Path("document.pdf"), engine, pages="1-3")
106
+
107
+ # 批量处理目录
108
+ from multi_ocr import ocr_directory
109
+ ocr_directory(Path("./scans/"), engine, concurrency=4)
110
+ ```
111
+
112
+ ### 自定义引擎
113
+
114
+ ```python
115
+ from multi_ocr import OCREngine
116
+
117
+ class MyEngine(OCREngine):
118
+ def parse_image(self, image_path: Path) -> str:
119
+ # 你的 OCR 逻辑
120
+ return "recognized text"
121
+ ```
122
+
123
+ ## 要求
124
+
125
+ - Python >= 3.11
126
+
127
+ ## 协议
128
+
129
+ MIT License
@@ -0,0 +1,103 @@
1
+ # multi-ocr
2
+
3
+ 多引擎 OCR 工具包,将 PDF 和图片转换为 Markdown 文档。
4
+
5
+ - **CLI 工具**:全局安装后一行命令完成 OCR
6
+ - **SDK 依赖**:作为 Python 库集成到你的项目中
7
+
8
+ ## 支持的引擎
9
+
10
+ | 引擎 | 说明 | 类型 |
11
+ |---|---|---|
12
+ | SiliconFlow + DeepSeek-OCR | 云端 OCR,精度高 | API |
13
+ | SiliconFlow + PaddleOCR-VL-1.5 | 云端 OCR,轻量快速 | API |
14
+ | DashScope + Qwen-VL-OCR | 阿里云百炼 | API |
15
+ | LiteParse | 本地 PDF 解析,无需联网 | 本地 |
16
+ | Ollama + DeepSeek-OCR | 本地部署 OCR | 本地 |
17
+
18
+ ## 安装
19
+
20
+ ### CLI 全局安装
21
+
22
+ ```bash
23
+ uv tool install multi-ocr
24
+ # 或
25
+ pip install multi-ocr
26
+ ```
27
+
28
+ ### SDK 依赖安装
29
+
30
+ ```bash
31
+ pip install multi-ocr
32
+ # 或
33
+ uv add multi-ocr
34
+ ```
35
+
36
+ ## CLI 使用
37
+
38
+ ```bash
39
+ # 单文件 OCR
40
+ multi-ocr document.pdf
41
+
42
+ # 指定引擎和页码范围
43
+ multi-ocr document.pdf --model dashscope-qwen-vl-ocr --pages 1-5
44
+
45
+ # 批量处理目录
46
+ multi-ocr ./scans/ --model silicon-deepseek-ocr -j 4
47
+
48
+ # 查看帮助
49
+ multi-ocr --help
50
+ ```
51
+
52
+ ### 环境变量
53
+
54
+ | 引擎 | 环境变量 |
55
+ |---|---|
56
+ | SiliconFlow | `SILICONFLOW_API_KEY` |
57
+ | DashScope | `DASHSCOPE_API_KEY` |
58
+ | Ollama | `OLLAMA_BASE_URL`(可选,默认 http://127.0.0.1:11434)|
59
+
60
+ 也可通过 `--api-key` 参数直接传入。
61
+
62
+ ## SDK 使用
63
+
64
+ ```python
65
+ from pathlib import Path
66
+ from multi_ocr import get_engine, ocr_file, OCREngine
67
+
68
+ # 创建引擎
69
+ engine = get_engine(
70
+ provider="siliconflow",
71
+ model="deepseek-ai/DeepSeek-OCR",
72
+ api_key="your-api-key",
73
+ )
74
+
75
+ # 识别图片
76
+ text = engine.parse_image(Path("scan.jpg"))
77
+
78
+ # 识别 PDF
79
+ result = ocr_file(Path("document.pdf"), engine, pages="1-3")
80
+
81
+ # 批量处理目录
82
+ from multi_ocr import ocr_directory
83
+ ocr_directory(Path("./scans/"), engine, concurrency=4)
84
+ ```
85
+
86
+ ### 自定义引擎
87
+
88
+ ```python
89
+ from multi_ocr import OCREngine
90
+
91
+ class MyEngine(OCREngine):
92
+ def parse_image(self, image_path: Path) -> str:
93
+ # 你的 OCR 逻辑
94
+ return "recognized text"
95
+ ```
96
+
97
+ ## 要求
98
+
99
+ - Python >= 3.11
100
+
101
+ ## 协议
102
+
103
+ MIT License
@@ -0,0 +1,101 @@
1
+ ---
2
+ title: Markdown Output | Developer Documentation
3
+ description: Render documents to clean, structured Markdown for LLMs and RAG pipelines.
4
+ ---
5
+
6
+ LiteParse can render documents directly to Markdown, reconstructing headings, tables, lists, images, and links from the spatial layout. This is ideal for feeding documents to LLMs and RAG pipelines, where clean, structured text matters more than exact visual fidelity.
7
+
8
+ Markdown is a first-class output format alongside `text` and `json`.
9
+
10
+ ## CLI
11
+
12
+ Terminal window
13
+
14
+ ```
15
+ # Render a document to Markdown
16
+ lit parse document.pdf --format markdown -o output.md
17
+
18
+
19
+ # Print Markdown to stdout
20
+ lit parse document.pdf --format markdown
21
+ ```
22
+
23
+ ### Images
24
+
25
+ By default, raster images are emitted as Markdown placeholders (`![](image_pN_K.png)`) in reading order. Control this with `--image-mode`:
26
+
27
+ | Mode | Behavior |
28
+ | ----------------------- | ----------------------------------------------------------------------- |
29
+ | `placeholder` (default) | Emit `![](image_pN_K.png)` references in reading order |
30
+ | `off` | Strip images entirely |
31
+ | `embed` | Write each image’s PNG bytes to `--image-output-dir` and reference them |
32
+
33
+ Terminal window
34
+
35
+ ```
36
+ # Strip images
37
+ lit parse document.pdf --format markdown --image-mode off
38
+
39
+
40
+ # Extract embedded images to disk and reference them from the markdown
41
+ lit parse document.pdf --format markdown --image-mode embed --image-output-dir ./images
42
+ ```
43
+
44
+ ### Links
45
+
46
+ Hyperlink annotations are rendered as `[text](url)` by default. Pass `--no-links` to emit the anchor text as plain text instead:
47
+
48
+ Terminal window
49
+
50
+ ```
51
+ lit parse document.pdf --format markdown --no-links
52
+ ```
53
+
54
+ ## Library
55
+
56
+ The rendered Markdown is returned on `result.text`.
57
+
58
+ ```
59
+ import { LiteParse } from "@llamaindex/liteparse";
60
+
61
+
62
+ const parser = new LiteParse({
63
+ outputFormat: "markdown", // "json" | "text" | "markdown"
64
+ imageMode: "placeholder", // "placeholder" | "off" | "embed" (default: "placeholder")
65
+ extractLinks: true, // render [text](url) link syntax (default: true)
66
+ });
67
+ const result = await parser.parse("document.pdf");
68
+ console.log(result.text); // rendered Markdown
69
+ ```
70
+
71
+ ```
72
+ from liteparse import LiteParse
73
+
74
+
75
+ parser = LiteParse(
76
+ output_format="markdown", # "json" | "text" | "markdown"
77
+ image_mode="placeholder", # "placeholder" | "off" | "embed"
78
+ extract_links=True, # render [text](url) link syntax (default: True)
79
+ )
80
+ result = parser.parse("document.pdf")
81
+ print(result.text) # rendered Markdown
82
+ ```
83
+
84
+ ```
85
+ use liteparse::config::{ImageMode, LiteParseConfig, OutputFormat};
86
+ use liteparse::LiteParse;
87
+
88
+
89
+ let config = LiteParseConfig {
90
+ output_format: OutputFormat::Markdown,
91
+ image_mode: ImageMode::Placeholder,
92
+ extract_links: true,
93
+ ..Default::default()
94
+ };
95
+ let result = LiteParse::new(config).parse("document.pdf").await?;
96
+ println!("{}", result.text); // rendered Markdown
97
+ ```
98
+
99
+ ## Quality notes
100
+
101
+ Markdown reconstruction quality varies with document complexity. LiteParse does a strong job on typical documents, handling prose, headings, simple-to-moderate tables, and lists. This runs entirely locally with no models using rule-based heuristics. For the hardest documents (dense or multi-level tables, complex multi-column layouts, charts, and scans), [LlamaParse](https://developers.llamaindex.ai/python/cloud/llamaparse/?utm_source=github\&utm_medium=liteparse) remains the most accurate option.