ingestlib 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 (156) hide show
  1. ingestlib-0.1.0/.claude/settings.local.json +11 -0
  2. ingestlib-0.1.0/.env.example +9 -0
  3. ingestlib-0.1.0/.gitignore +230 -0
  4. ingestlib-0.1.0/.python-version +1 -0
  5. ingestlib-0.1.0/LICENSE +21 -0
  6. ingestlib-0.1.0/Makefile +77 -0
  7. ingestlib-0.1.0/PKG-INFO +248 -0
  8. ingestlib-0.1.0/README.md +209 -0
  9. ingestlib-0.1.0/assets/cover.png +0 -0
  10. ingestlib-0.1.0/config.example.yaml +45 -0
  11. ingestlib-0.1.0/evals/dataset.yaml +146 -0
  12. ingestlib-0.1.0/evals/run_eval.py +166 -0
  13. ingestlib-0.1.0/pyproject.toml +80 -0
  14. ingestlib-0.1.0/src/ingestlib/__init__.py +4 -0
  15. ingestlib-0.1.0/src/ingestlib/config.py +231 -0
  16. ingestlib-0.1.0/src/ingestlib/foundations/__init__.py +10 -0
  17. ingestlib-0.1.0/src/ingestlib/foundations/llm/__init__.py +48 -0
  18. ingestlib-0.1.0/src/ingestlib/foundations/llm/bedrock/__init__.py +39 -0
  19. ingestlib-0.1.0/src/ingestlib/foundations/llm/bedrock/embedding.py +127 -0
  20. ingestlib-0.1.0/src/ingestlib/foundations/llm/bedrock/factory.py +101 -0
  21. ingestlib-0.1.0/src/ingestlib/foundations/llm/bedrock/nova.py +302 -0
  22. ingestlib-0.1.0/src/ingestlib/foundations/llm/bedrock/rerank.py +75 -0
  23. ingestlib-0.1.0/src/ingestlib/foundations/llm/jina/__init__.py +4 -0
  24. ingestlib-0.1.0/src/ingestlib/foundations/llm/jina/rerank.py +83 -0
  25. ingestlib-0.1.0/src/ingestlib/foundations/ocr/__init__.py +6 -0
  26. ingestlib-0.1.0/src/ingestlib/foundations/ocr/models.py +125 -0
  27. ingestlib-0.1.0/src/ingestlib/foundations/ocr/paddle_vl.py +272 -0
  28. ingestlib-0.1.0/src/ingestlib/operations/__init__.py +25 -0
  29. ingestlib-0.1.0/src/ingestlib/operations/classify/__init__.py +16 -0
  30. ingestlib-0.1.0/src/ingestlib/operations/classify/chunker.py +74 -0
  31. ingestlib-0.1.0/src/ingestlib/operations/classify/classifier.py +219 -0
  32. ingestlib-0.1.0/src/ingestlib/operations/classify/models.py +36 -0
  33. ingestlib-0.1.0/src/ingestlib/operations/parse/__init__.py +33 -0
  34. ingestlib-0.1.0/src/ingestlib/operations/parse/assembler.py +90 -0
  35. ingestlib-0.1.0/src/ingestlib/operations/parse/detector.py +28 -0
  36. ingestlib-0.1.0/src/ingestlib/operations/parse/enricher.py +124 -0
  37. ingestlib-0.1.0/src/ingestlib/operations/parse/loaders/__init__.py +39 -0
  38. ingestlib-0.1.0/src/ingestlib/operations/parse/loaders/office.py +117 -0
  39. ingestlib-0.1.0/src/ingestlib/operations/parse/loaders/pdf.py +185 -0
  40. ingestlib-0.1.0/src/ingestlib/operations/parse/models.py +162 -0
  41. ingestlib-0.1.0/src/ingestlib/operations/parse/pipeline.py +147 -0
  42. ingestlib-0.1.0/src/ingestlib/operations/parse/reviewer.py +136 -0
  43. ingestlib-0.1.0/src/ingestlib/operations/split/__init__.py +17 -0
  44. ingestlib-0.1.0/src/ingestlib/operations/split/models.py +90 -0
  45. ingestlib-0.1.0/src/ingestlib/operations/split/pages.py +182 -0
  46. ingestlib-0.1.0/src/ingestlib/operations/split/sections.py +119 -0
  47. ingestlib-0.1.0/src/ingestlib/operations/split/segmenter.py +172 -0
  48. ingestlib-0.1.0/src/ingestlib/operations/split/splitter.py +169 -0
  49. ingestlib-0.1.0/src/ingestlib/services/__init__.py +23 -0
  50. ingestlib-0.1.0/src/ingestlib/services/ingest/__init__.py +9 -0
  51. ingestlib-0.1.0/src/ingestlib/services/ingest/ingestor.py +152 -0
  52. ingestlib-0.1.0/src/ingestlib/services/ingest/models.py +30 -0
  53. ingestlib-0.1.0/src/ingestlib/services/retrieve/__init__.py +10 -0
  54. ingestlib-0.1.0/src/ingestlib/services/retrieve/models.py +43 -0
  55. ingestlib-0.1.0/src/ingestlib/services/retrieve/retriever.py +97 -0
  56. ingestlib-0.1.0/src/ingestlib/storage/__init__.py +49 -0
  57. ingestlib-0.1.0/src/ingestlib/storage/artifacts.py +337 -0
  58. ingestlib-0.1.0/src/ingestlib/storage/base.py +102 -0
  59. ingestlib-0.1.0/src/ingestlib/storage/pinecone/__init__.py +21 -0
  60. ingestlib-0.1.0/src/ingestlib/storage/pinecone/client.py +167 -0
  61. ingestlib-0.1.0/src/ingestlib/storage/pinecone/store.py +263 -0
  62. ingestlib-0.1.0/src/ingestlib/storage/qdrant/__init__.py +21 -0
  63. ingestlib-0.1.0/src/ingestlib/storage/qdrant/client.py +136 -0
  64. ingestlib-0.1.0/src/ingestlib/storage/qdrant/store.py +259 -0
  65. ingestlib-0.1.0/src/ingestlib/storage/s3/__init__.py +4 -0
  66. ingestlib-0.1.0/src/ingestlib/storage/s3/client.py +97 -0
  67. ingestlib-0.1.0/src/ingestlib/utils/__init__.py +7 -0
  68. ingestlib-0.1.0/src/ingestlib/utils/files.py +14 -0
  69. ingestlib-0.1.0/src/ingestlib/utils/logger.py +127 -0
  70. ingestlib-0.1.0/tests/__init__.py +0 -0
  71. ingestlib-0.1.0/tests/conftest.py +19 -0
  72. ingestlib-0.1.0/tests/data/images/document_chart.png +0 -0
  73. ingestlib-0.1.0/tests/data/images/document_text.png +0 -0
  74. ingestlib-0.1.0/tests/data/images/photo.jpg +0 -0
  75. ingestlib-0.1.0/tests/data/pdf/catastrophe-recap.pdf +0 -0
  76. ingestlib-0.1.0/tests/data/pdf/clean-energy.pdf +0 -0
  77. ingestlib-0.1.0/tests/data/pdf/clinical-study.pdf +0 -0
  78. ingestlib-0.1.0/tests/data/pdf/component-datasheet.pdf +0 -0
  79. ingestlib-0.1.0/tests/data/pdf/egov-survey.pdf +0 -0
  80. ingestlib-0.1.0/tests/data/pdf/esg-metrics.pdf +0 -0
  81. ingestlib-0.1.0/tests/data/pdf/finance-10k.pdf +0 -0
  82. ingestlib-0.1.0/tests/data/pdf/health-report.pdf +0 -0
  83. ingestlib-0.1.0/tests/data/pdf/insurance-acord.pdf +0 -0
  84. ingestlib-0.1.0/tests/data/pdf/manufacturing-report.pdf +0 -0
  85. ingestlib-0.1.0/tests/data/pdf/ny-timetable.pdf +0 -0
  86. ingestlib-0.1.0/tests/data/pdf/postal-10k.pdf +0 -0
  87. ingestlib-0.1.0/tests/data/pdf/purchase-agreement.pdf +0 -0
  88. ingestlib-0.1.0/tests/data/pdf/uber-earnings.pdf +0 -0
  89. ingestlib-0.1.0/tests/foundations/__init__.py +0 -0
  90. ingestlib-0.1.0/tests/foundations/llm/__init__.py +0 -0
  91. ingestlib-0.1.0/tests/foundations/llm/_shared.py +15 -0
  92. ingestlib-0.1.0/tests/foundations/llm/bedrock/__init__.py +0 -0
  93. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/__init__.py +0 -0
  94. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/conftest.py +80 -0
  95. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/test_async.py +59 -0
  96. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/test_errors.py +14 -0
  97. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/test_image.py +81 -0
  98. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/test_multimodal.py +65 -0
  99. ingestlib-0.1.0/tests/foundations/llm/bedrock/embedding/test_text.py +89 -0
  100. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/__init__.py +0 -0
  101. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/conftest.py +82 -0
  102. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_async.py +30 -0
  103. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_chat.py +35 -0
  104. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_chat_thinking.py +40 -0
  105. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_errors.py +24 -0
  106. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_langchain.py +49 -0
  107. ingestlib-0.1.0/tests/foundations/llm/bedrock/nova/test_structured.py +82 -0
  108. ingestlib-0.1.0/tests/foundations/llm/bedrock/rerank/__init__.py +0 -0
  109. ingestlib-0.1.0/tests/foundations/llm/bedrock/rerank/conftest.py +68 -0
  110. ingestlib-0.1.0/tests/foundations/llm/bedrock/rerank/test_async.py +25 -0
  111. ingestlib-0.1.0/tests/foundations/llm/bedrock/rerank/test_errors.py +15 -0
  112. ingestlib-0.1.0/tests/foundations/llm/bedrock/rerank/test_rerank.py +71 -0
  113. ingestlib-0.1.0/tests/foundations/llm/jina/__init__.py +0 -0
  114. ingestlib-0.1.0/tests/foundations/llm/jina/conftest.py +49 -0
  115. ingestlib-0.1.0/tests/foundations/llm/jina/test_async.py +21 -0
  116. ingestlib-0.1.0/tests/foundations/llm/jina/test_errors.py +27 -0
  117. ingestlib-0.1.0/tests/foundations/llm/jina/test_rerank.py +70 -0
  118. ingestlib-0.1.0/tests/foundations/ocr/__init__.py +0 -0
  119. ingestlib-0.1.0/tests/foundations/ocr/test_models.py +48 -0
  120. ingestlib-0.1.0/tests/foundations/ocr/test_paddle_vl.py +51 -0
  121. ingestlib-0.1.0/tests/operations/__init__.py +0 -0
  122. ingestlib-0.1.0/tests/operations/classify/__init__.py +0 -0
  123. ingestlib-0.1.0/tests/operations/classify/test_chunker.py +85 -0
  124. ingestlib-0.1.0/tests/operations/classify/test_classify_e2e.py +71 -0
  125. ingestlib-0.1.0/tests/operations/classify/test_models.py +22 -0
  126. ingestlib-0.1.0/tests/operations/parse/__init__.py +0 -0
  127. ingestlib-0.1.0/tests/operations/parse/test_assembler.py +85 -0
  128. ingestlib-0.1.0/tests/operations/parse/test_detector.py +29 -0
  129. ingestlib-0.1.0/tests/operations/parse/test_enricher.py +56 -0
  130. ingestlib-0.1.0/tests/operations/parse/test_models.py +82 -0
  131. ingestlib-0.1.0/tests/operations/parse/test_parse_e2e.py +78 -0
  132. ingestlib-0.1.0/tests/operations/split/__init__.py +0 -0
  133. ingestlib-0.1.0/tests/operations/split/test_models.py +31 -0
  134. ingestlib-0.1.0/tests/operations/split/test_pages.py +77 -0
  135. ingestlib-0.1.0/tests/operations/split/test_segmenter.py +70 -0
  136. ingestlib-0.1.0/tests/operations/split/test_split_e2e.py +49 -0
  137. ingestlib-0.1.0/tests/services/__init__.py +0 -0
  138. ingestlib-0.1.0/tests/services/ingest/__init__.py +0 -0
  139. ingestlib-0.1.0/tests/services/ingest/test_models.py +17 -0
  140. ingestlib-0.1.0/tests/services/retrieve/__init__.py +0 -0
  141. ingestlib-0.1.0/tests/services/retrieve/test_models.py +26 -0
  142. ingestlib-0.1.0/tests/services/test_services_e2e.py +70 -0
  143. ingestlib-0.1.0/tests/storage/__init__.py +0 -0
  144. ingestlib-0.1.0/tests/storage/pinecone/__init__.py +0 -0
  145. ingestlib-0.1.0/tests/storage/pinecone/test_hybrid.py +29 -0
  146. ingestlib-0.1.0/tests/storage/pinecone/test_mappings.py +39 -0
  147. ingestlib-0.1.0/tests/storage/pinecone/test_pinecone_e2e.py +115 -0
  148. ingestlib-0.1.0/tests/storage/qdrant/__init__.py +0 -0
  149. ingestlib-0.1.0/tests/storage/qdrant/test_mappings.py +47 -0
  150. ingestlib-0.1.0/tests/storage/qdrant/test_qdrant_e2e.py +120 -0
  151. ingestlib-0.1.0/tests/storage/test_artifacts_e2e.py +120 -0
  152. ingestlib-0.1.0/tests/storage/test_base.py +41 -0
  153. ingestlib-0.1.0/tests/storage/test_default_store.py +19 -0
  154. ingestlib-0.1.0/tests/utils/__init__.py +0 -0
  155. ingestlib-0.1.0/tests/utils/test_logger.py +48 -0
  156. ingestlib-0.1.0/uv.lock +4036 -0
@@ -0,0 +1,11 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "WebFetch(domain:www.llamaindex.ai)",
5
+ "WebFetch(domain:developers.llamaindex.ai)",
6
+ "WebSearch",
7
+ "WebFetch(domain:aws.amazon.com)",
8
+ "Bash(uv run *)"
9
+ ]
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ # Jina AI Reranker — https://jina.ai/api-dashboard/
2
+ JINA_API_KEY=jina_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
3
+
4
+ # Pinecone — https://app.pinecone.io/ → API Keys
5
+ PINECONE_API_KEY=pcsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
6
+
7
+ # Qdrant — https://cloud.qdrant.io/ → API Keys, or a self-hosted server
8
+ QDRANT_URL=http://localhost:6333
9
+ QDRANT_API_KEY=
@@ -0,0 +1,230 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[codz]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py.cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ # Pipfile.lock
96
+
97
+ # UV
98
+ # Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # uv.lock
102
+
103
+ # poetry
104
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
105
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
106
+ # commonly ignored for libraries.
107
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
108
+ # poetry.lock
109
+ # poetry.toml
110
+
111
+ # pdm
112
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
113
+ # pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
114
+ # https://pdm-project.org/en/latest/usage/project/#working-with-version-control
115
+ # pdm.lock
116
+ # pdm.toml
117
+ .pdm-python
118
+ .pdm-build/
119
+
120
+ # pixi
121
+ # Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
122
+ # pixi.lock
123
+ # Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
124
+ # in the .venv directory. It is recommended not to include this directory in version control.
125
+ .pixi
126
+
127
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
128
+ __pypackages__/
129
+
130
+ # Celery stuff
131
+ celerybeat-schedule
132
+ celerybeat.pid
133
+
134
+ # Redis
135
+ *.rdb
136
+ *.aof
137
+ *.pid
138
+
139
+ # RabbitMQ
140
+ mnesia/
141
+ rabbitmq/
142
+ rabbitmq-data/
143
+
144
+ # ActiveMQ
145
+ activemq-data/
146
+
147
+ # SageMath parsed files
148
+ *.sage.py
149
+
150
+ # Environments
151
+ .env
152
+ .envrc
153
+ .venv
154
+ env/
155
+ venv/
156
+ ENV/
157
+ env.bak/
158
+ venv.bak/
159
+
160
+ # Spyder project settings
161
+ .spyderproject
162
+ .spyproject
163
+
164
+ # Rope project settings
165
+ .ropeproject
166
+
167
+ # mkdocs documentation
168
+ /site
169
+
170
+ # mypy
171
+ .mypy_cache/
172
+ .dmypy.json
173
+ dmypy.json
174
+
175
+ # Pyre type checker
176
+ .pyre/
177
+
178
+ # pytype static type analyzer
179
+ .pytype/
180
+
181
+ # Cython debug symbols
182
+ cython_debug/
183
+
184
+ # PyCharm
185
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
186
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
187
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
188
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
189
+ # .idea/
190
+
191
+ # Abstra
192
+ # Abstra is an AI-powered process automation framework.
193
+ # Ignore directories containing user credentials, local state, and settings.
194
+ # Learn more at https://abstra.io/docs
195
+ .abstra/
196
+
197
+ # Visual Studio Code
198
+ # Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
199
+ # that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
200
+ # and can be added to the global gitignore or merged into this file. However, if you prefer,
201
+ # you could uncomment the following to ignore the entire vscode folder
202
+ # .vscode/
203
+ # Temporary file for partial code execution
204
+ tempCodeRunnerFile.py
205
+
206
+ # Ruff stuff:
207
+ .ruff_cache/
208
+
209
+ # PyPI configuration file
210
+ .pypirc
211
+
212
+ # Marimo
213
+ marimo/_static/
214
+ marimo/_lsp/
215
+ __marimo__/
216
+
217
+ # Streamlit
218
+ .streamlit/secrets.toml
219
+
220
+ # macOS
221
+ *.DS_Store
222
+
223
+ # Internal design notes — not for the public repo
224
+ plan.md
225
+
226
+ # Personal settings — copy config.example.yaml and fill in your values
227
+ config.yaml
228
+
229
+ # Eval score snapshots — local measurement history
230
+ evals/results/
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LangModule
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,77 @@
1
+ .PHONY: test test-all test-llm test-nova test-embedding test-rerank test-rerank-aws test-rerank-jina test-ocr test-parse test-classify test-split test-s3 test-pinecone test-qdrant test-services eval
2
+
3
+ # fast suite — every opt-in e2e group skips (RUN_* gates unset)
4
+ test:
5
+ uv run pytest tests/
6
+
7
+ # entire suite including every opt-in group (needs VL server running + Bedrock access)
8
+ test-all:
9
+ RUN_AWS_RERANK=1 RUN_OCR_E2E=1 RUN_PARSE_E2E=1 RUN_CLASSIFY_E2E=1 RUN_SPLIT_E2E=1 RUN_S3_E2E=1 RUN_PINECONE_E2E=1 RUN_QDRANT_E2E=1 RUN_SERVICES_E2E=1 uv run pytest tests/
10
+
11
+ # --- llm layer (mirrors src/ingestlib/foundations/llm/) ---
12
+
13
+ test-llm:
14
+ uv run pytest tests/foundations/llm/
15
+
16
+ test-nova:
17
+ uv run pytest tests/foundations/llm/bedrock/nova/
18
+
19
+ test-embedding:
20
+ uv run pytest tests/foundations/llm/bedrock/embedding/
21
+
22
+ # both providers — AWS-hitting tests skip without RUN_AWS_RERANK=1
23
+ test-rerank:
24
+ uv run pytest tests/foundations/llm/bedrock/rerank/ tests/foundations/llm/jina/
25
+
26
+ # opt-in: hits amazon.rerank-v1:0 (2 RPM quota — expect ~1 min of throttle sleeps)
27
+ test-rerank-aws:
28
+ RUN_AWS_RERANK=1 uv run pytest tests/foundations/llm/bedrock/rerank/
29
+
30
+ test-rerank-jina:
31
+ uv run pytest tests/foundations/llm/jina/
32
+
33
+ # --- ocr layer (mirrors src/ingestlib/foundations/ocr/) — needs the VL inference server ---
34
+
35
+ test-ocr:
36
+ RUN_OCR_E2E=1 uv run pytest tests/foundations/ocr/
37
+
38
+ # --- parse operation (mirrors src/ingestlib/operations/parse/) — needs VL server + Bedrock ---
39
+
40
+ test-parse:
41
+ RUN_PARSE_E2E=1 uv run pytest tests/operations/parse/
42
+
43
+ # --- classify operation (mirrors src/ingestlib/operations/classify/) — needs Bedrock ---
44
+
45
+ test-classify:
46
+ RUN_CLASSIFY_E2E=1 uv run pytest tests/operations/classify/
47
+
48
+ # --- split operation (mirrors src/ingestlib/operations/split/) — needs Bedrock ---
49
+
50
+ test-split:
51
+ RUN_SPLIT_E2E=1 uv run pytest tests/operations/split/
52
+
53
+ # --- storage (S3 artifacts) — needs AWS credentials ---
54
+
55
+ test-s3:
56
+ RUN_S3_E2E=1 uv run pytest tests/storage/
57
+
58
+ # --- pinecone connector — needs PINECONE_API_KEY + Bedrock (embeddings) ---
59
+
60
+ test-pinecone:
61
+ RUN_PINECONE_E2E=1 uv run pytest tests/storage/pinecone/
62
+
63
+ # --- qdrant connector — needs a Qdrant server at QDRANT_URL + Bedrock ---
64
+
65
+ test-qdrant:
66
+ RUN_QDRANT_E2E=1 uv run pytest tests/storage/qdrant/
67
+
68
+ # --- services (ingest + retrieve) — needs the FULL stack ---
69
+
70
+ test-services:
71
+ RUN_SERVICES_E2E=1 uv run pytest tests/services/
72
+
73
+ # --- retrieval quality eval — measurement, not a test (needs the full stack;
74
+ # first run also needs the VL server to ingest the fixture corpus) ---
75
+
76
+ eval:
77
+ uv run python evals/run_eval.py
@@ -0,0 +1,248 @@
1
+ Metadata-Version: 2.4
2
+ Name: ingestlib
3
+ Version: 0.1.0
4
+ Summary: Self-hosted document intelligence for RAG — parse, classify, and split PDF/DOCX/PPTX into searchable, cited, retrieval-ready chunks
5
+ Project-URL: Homepage, https://github.com/LangModule/ingestlib
6
+ Project-URL: Repository, https://github.com/LangModule/ingestlib
7
+ Project-URL: Issues, https://github.com/LangModule/ingestlib/issues
8
+ Author-email: ramacharanreddy-k <ramacharanreddykasireddy@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: chunking,document-intelligence,document-parsing,hybrid-search,ocr,rag,retrieval
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: MacOS
15
+ Classifier: Operating System :: POSIX :: Linux
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Text Processing :: Indexing
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: boto3>=1.43.29
23
+ Requires-Dist: botocore[crt]>=1.43
24
+ Requires-Dist: fastembed>=0.8.0
25
+ Requires-Dist: httpx>=0.27
26
+ Requires-Dist: langchain-aws>=1.5.1
27
+ Requires-Dist: mlx-vlm>=0.6.4; sys_platform == 'darwin' and platform_machine == 'arm64'
28
+ Requires-Dist: paddleocr>=3.7.0
29
+ Requires-Dist: paddlepaddle>=3.3.1
30
+ Requires-Dist: paddlex[genai-client,ocr]==3.7.1
31
+ Requires-Dist: pillow>=10.0
32
+ Requires-Dist: pinecone>=9.1.0
33
+ Requires-Dist: pydantic>=2.0
34
+ Requires-Dist: pypdfium2>=4.0
35
+ Requires-Dist: python-dotenv>=1.0
36
+ Requires-Dist: pyyaml>=6.0.2
37
+ Requires-Dist: qdrant-client>=1.18.0
38
+ Description-Content-Type: text/markdown
39
+
40
+ # ingestlib
41
+
42
+ ![ingestlib — self-hosted document intelligence for RAG](assets/cover.png)
43
+
44
+ Self-hosted document intelligence for RAG pipelines. One library that takes a
45
+ raw document — PDF, DOCX, PPTX — and produces searchable, **cited**,
46
+ retrieval-ready chunks: the territory of LlamaParse / Reducto /
47
+ Unstructured.io, running on your own stack.
48
+
49
+ ```python
50
+ from ingestlib.services import ingest, retrieve
51
+
52
+ ingest("finance-10k.pdf") # parse → classify → split → embed → vector store
53
+ result = retrieve("what were the total revenues?")
54
+ print(result.context) # ranked chunks, each citing doc · page · section
55
+ ```
56
+
57
+ ## What it does
58
+
59
+ | Stage | What you get |
60
+ |---|---|
61
+ | **Parse** | Layout-aware markdown per page: tables as HTML (merged cells intact), formulas as LaTeX, **charts converted to data tables** (estimated values marked `~`, printed callouts and growth labels captured), figures extracted as PNG crops with captions and AI descriptions — every block traceable to a bounding box on the page |
62
+ | **Classify** | Document-type label (`invoice`, `research_paper`, …) — open-ended or constrained to your categories, with confidence and alternatives. Works standalone with **no OCR** |
63
+ | **Split** | Sections (pages grouped by role: `methods`, `results`, …) containing **natural chunks** — boundaries follow the content, tables never split, each chunk carries a `[category › section › heading]` breadcrumb in its `embedding_text` |
64
+ | **Ingest** | The whole pipeline in one call, every stage persisted to S3, vectors upserted, deduplicated by content checksum |
65
+ | **Retrieve** | Question → **hybrid search** (dense embeddings + lexical sparse, merged) → **Jina rerank** → hits with scores and citations, plus a prompt-ready context block |
66
+
67
+ Engines: **PaddleOCR-VL-1.6** (0.9B VLM, runs on your GPU) for layout + recognition,
68
+ **Amazon Nova 2 Lite** for judgment (chart reading, review, classification,
69
+ chunk boundaries), **Nova multimodal embeddings**, **Pinecone or Qdrant** for
70
+ vectors (both hybrid dense + sparse), **S3** for artifacts. ~$0.002/page in LLM spend.
71
+
72
+ ## Quickstart
73
+
74
+ ### 1. Requirements
75
+
76
+ - Python 3.12+ and [uv](https://github.com/astral-sh/uv)
77
+ - **AWS account** with Bedrock access (`us-east-1`): Nova 2 Lite + Nova 2
78
+ multimodal embeddings
79
+ - **Vector database** — Pinecone account (serverless, free tier works;
80
+ the default) or a Qdrant server (local docker or Qdrant Cloud)
81
+ - **Jina AI account** for reranking (free tier: 100 RPM)
82
+
83
+ ### 2. Install
84
+
85
+ ```bash
86
+ git clone https://github.com/LangModule/ingestlib.git
87
+ cd ingestlib
88
+ uv sync
89
+ ```
90
+
91
+ System dependency — LibreOffice (DOCX/PPTX → PDF conversion):
92
+
93
+ ```bash
94
+ brew install --cask libreoffice # macOS (binary is `soffice`)
95
+ sudo apt install libreoffice-core libreoffice-writer libreoffice-impress # Linux
96
+ ```
97
+
98
+ ### 3. Start the OCR inference server
99
+
100
+ Parse runs PaddleOCR-VL-1.6 behind an inference server. First launch downloads
101
+ ~1.8 GB of weights; later launches load from cache in seconds.
102
+
103
+ ```bash
104
+ # Apple Silicon (Metal GPU)
105
+ uv run python -m mlx_vlm.server --port 8111 --model PaddlePaddle/PaddleOCR-VL-1.6
106
+
107
+ # NVIDIA (then set paddle_vl.backend: vllm-server in config.yaml)
108
+ vllm serve PaddlePaddle/PaddleOCR-VL-1.6 --port 8111
109
+ ```
110
+
111
+ The layout model (PP-DocLayoutV3, ~126 MB) auto-downloads on the first parse.
112
+
113
+ ### 4. Configure
114
+
115
+ ```bash
116
+ cp .env.example .env # paste your API keys (Jina + Pinecone and/or Qdrant)
117
+ cp config.example.yaml config.yaml # your AWS profile, bucket name, vector store choice
118
+ aws configure --profile your-aws-profile # Bedrock-enabled credentials
119
+ ```
120
+
121
+ Edit `config.yaml`: your AWS profile/account, S3 bucket name (globally
122
+ unique), vector store choice and index/collection names. **The S3 bucket and
123
+ the vector indexes/collection are created automatically on first use** — no
124
+ manual setup.
125
+
126
+ Config is discovered at call time, never at import: `INGESTLIB_CONFIG=/path/to/config.yaml`
127
+ wins, otherwise the working directory and its parents are searched — so
128
+ installed usage works the same as running inside this repo.
129
+
130
+ ### 5. Run
131
+
132
+ ```python
133
+ from ingestlib.services import ingest, retrieve
134
+
135
+ r = ingest("report.pdf")
136
+ print(r.status, r.category, r.chunks, r.durations)
137
+
138
+ res = retrieve("what does the report conclude?", top_k=5)
139
+ for hit in res.hits:
140
+ print(hit.rerank_score, hit.citation, hit.chunk.heading)
141
+ ```
142
+
143
+ ## Using the operations directly
144
+
145
+ Every operation also works standalone:
146
+
147
+ ```python
148
+ from ingestlib.operations import parse, classify, split
149
+
150
+ result = parse("report.pdf") # ParseResult: pages, regions, figures
151
+ print(result.markdown) # whole-document markdown
152
+ result.save_images("out/") # extracted figures/charts as PNGs
153
+
154
+ label = classify("report.pdf") # no OCR needed — native text + embedded images
155
+ chunks = split(result, category=label.category)
156
+ for c in chunks.chunks:
157
+ print(c.token_estimate, c.embedding_text.splitlines()[0])
158
+ ```
159
+
160
+ Persistence and vector access are explicit too:
161
+
162
+ ```python
163
+ from ingestlib.storage import artifacts, PineconeStore
164
+
165
+ doc_id = artifacts.save_parse(result) # S3: source, result.json, page PNGs, crops
166
+ artifacts.list_documents() # registry: filename, pages, category, chunks
167
+ ```
168
+
169
+ ## Architecture
170
+
171
+ ```
172
+ src/ingestlib/
173
+ ├── services/ ingest · retrieve — the product
174
+ ├── operations/ parse · classify · split — the tools (each standalone)
175
+ ├── storage/ artifacts (S3) · base (VectorStore contract) · pinecone · qdrant
176
+ ├── foundations/ llm (Bedrock Nova, Jina) · ocr (PaddleOCR-VL)
177
+ ├── utils/ logger · files
178
+ └── config.py config.yaml + .env → typed configs
179
+ ```
180
+
181
+ Strict downward dependencies. The `VectorStore` contract means backends drop
182
+ in as connectors — both ship **hybrid search**: **Pinecone** (dense + hosted
183
+ sparse model, merged client-side) and **Qdrant** (dense + BM25 with
184
+ server-side IDF and RRF fusion; local docker or cloud). Pick one with
185
+ `vector_store: pinecone | qdrant` in config.yaml. Keys for both can sit in
186
+ `.env` — only the selected connector ever builds a client.
187
+
188
+ ## Logging
189
+
190
+ ```bash
191
+ INGESTLIB_LOG_LEVEL=INFO # DEBUG | INFO | WARNING | ERROR (default INFO)
192
+ INGESTLIB_LOG_THIRD_PARTY=1 # also show paddlex/httpx/botocore chatter
193
+ INGESTLIB_LOG_COLOR=0 # disable colored output
194
+ ```
195
+
196
+ ## Testing
197
+
198
+ Tests hit **real APIs, never mocks**. Pure logic runs always; server-hitting
199
+ suites are opt-in via env gates.
200
+
201
+ ```bash
202
+ make test # fast suite (~180 tests, ~90s; e2e groups skip)
203
+ make test-parse # parse e2e (needs VL server + Bedrock)
204
+ make test-classify # classify e2e (needs Bedrock)
205
+ make test-split # split e2e (needs Bedrock)
206
+ make test-s3 # artifact store e2e (needs AWS)
207
+ make test-pinecone # vector connector e2e (needs Pinecone + Bedrock)
208
+ make test-qdrant # vector connector e2e (needs a Qdrant server + Bedrock)
209
+ make test-services # full product e2e (needs the entire stack)
210
+ make test-all # everything
211
+ make eval # retrieval quality eval (see below)
212
+ ```
213
+
214
+ Fixture PDFs live in `tests/data/pdf/` — 14 real documents (research papers,
215
+ earnings decks, insurance forms, timetables, 10-Ks).
216
+
217
+ ### Retrieval quality
218
+
219
+ Beyond pass/fail tests, `evals/` measures retrieval quality: 22 ground-truth
220
+ questions over the fixture corpus, run through the real `retrieve()` flow
221
+ under dense/hybrid × rerank on/off, scored by hit@k and MRR. Measured so far:
222
+ **with reranking, every answer lands in the top 3 hits (hit@3 = 1.00)**;
223
+ hit@1 ranges 0.86–1.00 across runs. Each run saves a timestamped snapshot to
224
+ `evals/results/`, so quality changes are visible over time.
225
+
226
+ ## Disk footprint
227
+
228
+ | Component | Size | Location |
229
+ |---|---|---|
230
+ | Python deps | ~3 GB | `.venv/` |
231
+ | PaddleOCR-VL-1.6 weights | ~1.8 GB | `~/.cache/huggingface/hub/` |
232
+ | PP-DocLayoutV3 | ~126 MB | `~/.paddlex/official_models/` |
233
+ | LibreOffice | ~600 MB | system |
234
+
235
+ ## Scope
236
+
237
+ English documents; PDF / DOCX / PPTX input. Images, charts, and tables
238
+ **inside** documents are fully extracted and interpreted; direct image files
239
+ and handwriting are out of scope by design.
240
+
241
+ ## Roadmap
242
+
243
+ - Hover-highlight review UI (bbox provenance already shipped for it)
244
+ - Extract: schema-driven field extraction with source provenance
245
+
246
+ ## License
247
+
248
+ See [LICENSE](./LICENSE).