mtt-converter 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 (29) hide show
  1. mtt_converter-0.1.0/.gitignore +224 -0
  2. mtt_converter-0.1.0/.python-version +1 -0
  3. mtt_converter-0.1.0/LICENSE +21 -0
  4. mtt_converter-0.1.0/PKG-INFO +112 -0
  5. mtt_converter-0.1.0/README.md +97 -0
  6. mtt_converter-0.1.0/main.py +6 -0
  7. mtt_converter-0.1.0/pyproject.toml +22 -0
  8. mtt_converter-0.1.0/src/mtt/__init__.py +1 -0
  9. mtt_converter-0.1.0/src/mtt/converter.py +96 -0
  10. mtt_converter-0.1.0/src/mtt/service/__init__.py +0 -0
  11. mtt_converter-0.1.0/src/mtt/service/caption_explaner/__init__.py +1 -0
  12. mtt_converter-0.1.0/src/mtt/service/caption_explaner/service.py +15 -0
  13. mtt_converter-0.1.0/src/mtt/service/docling/__init__.py +3 -0
  14. mtt_converter-0.1.0/src/mtt/service/docling/service.py +20 -0
  15. mtt_converter-0.1.0/src/mtt/service/mesh_llm/__init__.py +3 -0
  16. mtt_converter-0.1.0/src/mtt/service/mesh_llm/service.py +29 -0
  17. mtt_converter-0.1.0/src/mtt/types.py +11 -0
  18. mtt_converter-0.1.0/src/mtt/utils/__init__.py +0 -0
  19. mtt_converter-0.1.0/src/mtt/utils/caption_utils.py +84 -0
  20. mtt_converter-0.1.0/src/mtt/utils/docling_utils.py +18 -0
  21. mtt_converter-0.1.0/src/mtt/utils/mesh_llm_utils.py +167 -0
  22. mtt_converter-0.1.0/src/mtt/utils/tools/document_tools.py +8 -0
  23. mtt_converter-0.1.0/src/mtt/utils/tools/image_tools.py +10 -0
  24. mtt_converter-0.1.0/src/mtt/utils/tools/mesh_geometry.py +113 -0
  25. mtt_converter-0.1.0/src/mtt/utils/tools/obj_parser.py +37 -0
  26. mtt_converter-0.1.0/src/mtt/utils/tools/ply_parser.py +127 -0
  27. mtt_converter-0.1.0/src/mtt/utils/tools/stl_parser.py +156 -0
  28. mtt_converter-0.1.0/src/mtt/utils/tools/threemf_parser.py +52 -0
  29. mtt_converter-0.1.0/uv.lock +2897 -0
@@ -0,0 +1,224 @@
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
+ # Claude Code
221
+ .claude
222
+
223
+ # In test
224
+ .test_resource
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KIMJUNHEE9339
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,112 @@
1
+ Metadata-Version: 2.4
2
+ Name: mtt-converter
3
+ Version: 0.1.0
4
+ Summary: Add your description here
5
+ License-File: LICENSE
6
+ Requires-Python: >=3.12
7
+ Requires-Dist: anthropic>=0.117.1
8
+ Requires-Dist: beautifulsoup4>=4.15.0
9
+ Requires-Dist: docling[rapidocr]>=2.114.0
10
+ Requires-Dist: google-genai>=2.12.1
11
+ Requires-Dist: markdown>=3.10.2
12
+ Requires-Dist: openai>=2.46.0
13
+ Requires-Dist: python-dotenv>=1.2.2
14
+ Description-Content-Type: text/markdown
15
+
16
+ # mtt-converter
17
+
18
+ multiform data to text converter — 문서, 이미지, 3D 모델 등 다양한 형태의 데이터를 텍스트로 변환해주는 멀티모달 파이썬 라이브러리.
19
+
20
+ ## 설치
21
+
22
+ ```bash
23
+ pip install mtt-converter
24
+ ```
25
+
26
+ Python 3.12 이상이 필요합니다.
27
+
28
+ ## 빠른 시작
29
+
30
+ ```python
31
+ from mtt import MultiModalConverter
32
+
33
+ mc = MultiModalConverter()
34
+
35
+ # 확장자를 보고 mode를 자동으로 추정
36
+ text = mc.convert("report.pdf")
37
+
38
+ # mode를 직접 지정
39
+ text = mc.convert("photo.png", mode="ocr")
40
+ ```
41
+
42
+ `mode`를 넘기지 않으면 파일 확장자로 자동 추정하며, 이때 경고 메시지가 출력됩니다.
43
+
44
+ ## 지원하는 mode
45
+
46
+ | mode | 설명 | 지원 확장자 |
47
+ | --- | --- | --- |
48
+ | `doc` | 문서를 텍스트로 변환 ([docling](https://github.com/docling-project/docling) 사용) | `.pdf` `.doc` `.docx` `.ppt` `.pptx` `.xls` `.xlsx` `.html` `.htm` `.md` `.csv` |
49
+ | `ocr` | 이미지 속 텍스트를 OCR로 추출 (docling 사용) | 직접 호출 시 임의의 이미지 파일 |
50
+ | `caption` | 이미지 내용을 멀티모달 LLM으로 캡셔닝/설명 | `.jpg` `.jpeg` `.tif` `.tiff` `.png` `.bmp` |
51
+ | `3dmodel` | 3D 모델 파일을 파싱해 지오메트리 요약(바운딩 박스, 표면적, 부피 등)을 텍스트로 반환 | `.stl` `.obj` `.ply` `.3mf` |
52
+
53
+ > `.glb`도 `3dmodel`로 추정되지만 아직 파서가 구현되어 있지 않습니다.
54
+
55
+ ## 사용 예시
56
+
57
+ ### 문서 → 텍스트
58
+
59
+ ```python
60
+ mc.convert("report.pdf", mode="doc")
61
+ ```
62
+
63
+ ### 이미지 OCR
64
+
65
+ ```python
66
+ mc.convert("scanned_page.png", mode="ocr")
67
+ ```
68
+
69
+ ### 이미지 캡셔닝
70
+
71
+ Gemini, GPT-4o, Claude 중 하나로 이미지를 설명합니다. 사용할 모델과 API 키는 `MultiModalConverter` 생성 시 지정합니다.
72
+ * **Token cost**가 발생할 수 있습니다.
73
+
74
+ ```python
75
+ mc = MultiModalConverter(model_name="gemini-3.5-flash", api_key="...")
76
+ mc.convert("photo.jpg", mode="caption", sub_prompt="이 사진을 한국어로 설명해줘.")
77
+ ```
78
+
79
+ - `model_name`: `"gemini-*"` / `"gpt-4o"` / `"claude-*"` 중 하나의 실제 API 모델 id (기본값 `"gemini-3.5-flash"`)
80
+ - `api_key`를 넘기지 않으면 각 provider SDK가 환경 변수(`GOOGLE_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`)에서 자동으로 읽습니다.
81
+ - `sub_prompt`를 지정하지 않으면 기본 프롬프트(`"Describe image in detail."`)가 사용됩니다.
82
+
83
+ ### 3D 모델 파싱
84
+
85
+ ```python
86
+ mc.convert("model.stl", mode="3dmodel")
87
+ ```
88
+
89
+ 솔리드 이름, 삼각형 개수, 바운딩 박스, 표면적, 부피(근사) 등을 요약한 텍스트를 반환합니다.
90
+
91
+ ## 출력 형식
92
+
93
+ 모든 `convert`/모드별 메서드는 `markdown` 파라미터를 받습니다.
94
+
95
+ ```python
96
+ mc.convert("report.pdf", markdown=False) # 마크다운 서식 없는 일반 텍스트
97
+ ```
98
+
99
+ 기본값은 `markdown=True`입니다.
100
+
101
+ ## 로드맵 (v1 기준 현황)
102
+
103
+ - ✅ 문서 변환 (docling)
104
+ - ✅ 이미지 OCR (docling)
105
+ - ✅ 이미지 캡셔닝 (Gemini / GPT-4o / Claude)
106
+ - ✅ 3D 모델 파싱: `.stl`, `.obj`, `.ply`, `.3mf`
107
+ - 🚧 3D 모델 파싱: `.step`/`.stp`, `.usd`/`.usdz`, `.fbx` — PointNet 기반 임베딩 후 기존 파서로 구축한 DB에서 유사 형상을 검색/리매핑하는 방식으로 구현 예정 (v2)
108
+ - 🚧 임베딩 함수 제공 (시간이 되면)
109
+
110
+ ## 라이선스
111
+
112
+ [MIT](./LICENSE)
@@ -0,0 +1,97 @@
1
+ # mtt-converter
2
+
3
+ multiform data to text converter — 문서, 이미지, 3D 모델 등 다양한 형태의 데이터를 텍스트로 변환해주는 멀티모달 파이썬 라이브러리.
4
+
5
+ ## 설치
6
+
7
+ ```bash
8
+ pip install mtt-converter
9
+ ```
10
+
11
+ Python 3.12 이상이 필요합니다.
12
+
13
+ ## 빠른 시작
14
+
15
+ ```python
16
+ from mtt import MultiModalConverter
17
+
18
+ mc = MultiModalConverter()
19
+
20
+ # 확장자를 보고 mode를 자동으로 추정
21
+ text = mc.convert("report.pdf")
22
+
23
+ # mode를 직접 지정
24
+ text = mc.convert("photo.png", mode="ocr")
25
+ ```
26
+
27
+ `mode`를 넘기지 않으면 파일 확장자로 자동 추정하며, 이때 경고 메시지가 출력됩니다.
28
+
29
+ ## 지원하는 mode
30
+
31
+ | mode | 설명 | 지원 확장자 |
32
+ | --- | --- | --- |
33
+ | `doc` | 문서를 텍스트로 변환 ([docling](https://github.com/docling-project/docling) 사용) | `.pdf` `.doc` `.docx` `.ppt` `.pptx` `.xls` `.xlsx` `.html` `.htm` `.md` `.csv` |
34
+ | `ocr` | 이미지 속 텍스트를 OCR로 추출 (docling 사용) | 직접 호출 시 임의의 이미지 파일 |
35
+ | `caption` | 이미지 내용을 멀티모달 LLM으로 캡셔닝/설명 | `.jpg` `.jpeg` `.tif` `.tiff` `.png` `.bmp` |
36
+ | `3dmodel` | 3D 모델 파일을 파싱해 지오메트리 요약(바운딩 박스, 표면적, 부피 등)을 텍스트로 반환 | `.stl` `.obj` `.ply` `.3mf` |
37
+
38
+ > `.glb`도 `3dmodel`로 추정되지만 아직 파서가 구현되어 있지 않습니다.
39
+
40
+ ## 사용 예시
41
+
42
+ ### 문서 → 텍스트
43
+
44
+ ```python
45
+ mc.convert("report.pdf", mode="doc")
46
+ ```
47
+
48
+ ### 이미지 OCR
49
+
50
+ ```python
51
+ mc.convert("scanned_page.png", mode="ocr")
52
+ ```
53
+
54
+ ### 이미지 캡셔닝
55
+
56
+ Gemini, GPT-4o, Claude 중 하나로 이미지를 설명합니다. 사용할 모델과 API 키는 `MultiModalConverter` 생성 시 지정합니다.
57
+ * **Token cost**가 발생할 수 있습니다.
58
+
59
+ ```python
60
+ mc = MultiModalConverter(model_name="gemini-3.5-flash", api_key="...")
61
+ mc.convert("photo.jpg", mode="caption", sub_prompt="이 사진을 한국어로 설명해줘.")
62
+ ```
63
+
64
+ - `model_name`: `"gemini-*"` / `"gpt-4o"` / `"claude-*"` 중 하나의 실제 API 모델 id (기본값 `"gemini-3.5-flash"`)
65
+ - `api_key`를 넘기지 않으면 각 provider SDK가 환경 변수(`GOOGLE_API_KEY`, `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`)에서 자동으로 읽습니다.
66
+ - `sub_prompt`를 지정하지 않으면 기본 프롬프트(`"Describe image in detail."`)가 사용됩니다.
67
+
68
+ ### 3D 모델 파싱
69
+
70
+ ```python
71
+ mc.convert("model.stl", mode="3dmodel")
72
+ ```
73
+
74
+ 솔리드 이름, 삼각형 개수, 바운딩 박스, 표면적, 부피(근사) 등을 요약한 텍스트를 반환합니다.
75
+
76
+ ## 출력 형식
77
+
78
+ 모든 `convert`/모드별 메서드는 `markdown` 파라미터를 받습니다.
79
+
80
+ ```python
81
+ mc.convert("report.pdf", markdown=False) # 마크다운 서식 없는 일반 텍스트
82
+ ```
83
+
84
+ 기본값은 `markdown=True`입니다.
85
+
86
+ ## 로드맵 (v1 기준 현황)
87
+
88
+ - ✅ 문서 변환 (docling)
89
+ - ✅ 이미지 OCR (docling)
90
+ - ✅ 이미지 캡셔닝 (Gemini / GPT-4o / Claude)
91
+ - ✅ 3D 모델 파싱: `.stl`, `.obj`, `.ply`, `.3mf`
92
+ - 🚧 3D 모델 파싱: `.step`/`.stp`, `.usd`/`.usdz`, `.fbx` — PointNet 기반 임베딩 후 기존 파서로 구축한 DB에서 유사 형상을 검색/리매핑하는 방식으로 구현 예정 (v2)
93
+ - 🚧 임베딩 함수 제공 (시간이 되면)
94
+
95
+ ## 라이선스
96
+
97
+ [MIT](./LICENSE)
@@ -0,0 +1,6 @@
1
+ def main():
2
+ print("Hello from mtt-converter!")
3
+
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -0,0 +1,22 @@
1
+ [project]
2
+ name = "mtt-converter"
3
+ version = "0.1.0"
4
+ description = "Add your description here"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "docling[rapidocr]>=2.114.0",
9
+ "google-genai>=2.12.1",
10
+ "markdown>=3.10.2",
11
+ "beautifulsoup4>=4.15.0",
12
+ "python-dotenv>=1.2.2",
13
+ "anthropic>=0.117.1",
14
+ "openai>=2.46.0",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["hatchling"]
19
+ build-backend = "hatchling.build"
20
+
21
+ [tool.hatch.build.targets.wheel]
22
+ packages = ["src/mtt"]
@@ -0,0 +1 @@
1
+ from .converter import MultiModalConverter
@@ -0,0 +1,96 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from mtt.service.docling import DoclingService
5
+ from mtt.service.mesh_llm import MeshLLMService
6
+ from mtt.service.caption_explaner import CaptionExplanerService
7
+ from mtt.types import ModeType
8
+
9
+
10
+ class MultiModalConverter:
11
+ MODE_ESTIMATE_MAP: dict[str, ModeType] = {
12
+ ".jpg": "caption",
13
+ ".jpeg": "caption",
14
+ ".tif": "caption",
15
+ ".tiff": "caption",
16
+ ".png": "caption",
17
+ ".bmp": "caption",
18
+ ".pdf": "doc",
19
+ ".doc": "doc",
20
+ ".docx": "doc",
21
+ ".ppt": "doc",
22
+ ".pptx": "doc",
23
+ ".xls": "doc",
24
+ ".xlsx": "doc",
25
+ ".html": "doc",
26
+ ".htm": "doc",
27
+ ".md": "doc",
28
+ ".csv": "doc",
29
+ ".stl": "3dmodel",
30
+ ".obj": "3dmodel",
31
+ ".ply": "3dmodel",
32
+ ".3mf": "3dmodel",
33
+ ".glb": "3dmodel",
34
+ }
35
+
36
+ def __init__(self, **kwargs):
37
+ # TODO: 나중에 임베딩 모델 api 관련해서 파라미터를 받을 수 있게하거나 할듯. 그리고 일부 시스템 프롬프트를 조절할 수 있게 할듯.
38
+ self._docling_service = DoclingService()
39
+ self._mesh_llm_service = MeshLLMService()
40
+ self._caption_explaner_service = CaptionExplanerService(
41
+ model_name=kwargs.get("model_name", "gemini-3.5-flash"), # default: gemini
42
+ api_key=kwargs.get("api_key")
43
+ )
44
+
45
+ def convert(self, input_path: str | Path, sub_prompt=None, markdown=True, mode: ModeType | None = None):
46
+ if sub_prompt is None:
47
+ sub_prompt = "Describe image in detail."
48
+
49
+ if mode is None:
50
+ print("[Warning] The 'mode' argument is missing, so the 'mode' value is estimated and used.")
51
+ _, ext = os.path.splitext(input_path)
52
+
53
+ mode = self.MODE_ESTIMATE_MAP.get(ext.lower())
54
+ print(f"[Warning] the mode was set to {mode}")
55
+
56
+ if mode == "caption":
57
+ # input 가공 가능
58
+ return self.caption(input_path, sub_prompt=sub_prompt, markdown=markdown)
59
+ elif mode == "ocr":
60
+ # input 가공 가능
61
+ return self.ocr(input_path, markdown=markdown)
62
+ elif mode == "3dmodel":
63
+ # input 가공 가능함.
64
+ return self.scan3dmodel(input_path, markdown=markdown)
65
+ elif mode in ["doc", "docs", "document"]:
66
+ # input 가공 가능함.
67
+ return self.doc2text(input_path, markdown=markdown)
68
+ else:
69
+ raise ValueError(f"There is no valid function for the mode. | mode: {mode}")
70
+
71
+
72
+
73
+ def caption(self, input_path: str | Path, sub_prompt=None, markdown=True) -> str:
74
+ '''
75
+ image의 정보를 텍스트로 설명 ; 캡셔닝
76
+ '''
77
+ return self._caption_explaner_service.to_text(input_path, sub_prompt=sub_prompt, markdown=markdown) #이미지 용 멀티모달 임베딩 api를 찾아서 구현할듯.
78
+
79
+ def ocr(self, input_path: str | Path, markdown=True) -> str:
80
+ '''
81
+ image내 텍스트를 ocr하여 얻어옴.
82
+ '''
83
+ return self._docling_service.to_text(input_path, markdown=markdown)
84
+
85
+ def scan3dmodel(self, input_path: str | Path, markdown=True) -> str:
86
+ '''
87
+ 3D 모델을 텍스트로 설명
88
+ '''
89
+ return self._mesh_llm_service.to_text(input_path, markdown=markdown) # TODO: point net과 parser들로 구현할 예정 ; 가능한 parser는 claude가 이미 구현한듯?
90
+
91
+ def doc2text(self, input_path: str | Path, markdown=True) -> str:
92
+ '''
93
+ 문서를 텍스트로 변환 [docling 모듈을 이용]
94
+ '''
95
+ return self._docling_service.to_text(input_path, markdown=markdown)
96
+ # 만약 docling관련해서 분리가 필요하면 분리하기.
File without changes
@@ -0,0 +1 @@
1
+ from .service import CaptionExplanerService
@@ -0,0 +1,15 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from mtt.types import CaptionModelType as ModelType
5
+ from mtt.utils.caption_utils import caption_explain, chat_output_to_text
6
+
7
+
8
+ class CaptionExplanerService:
9
+ def __init__(self, model_name:ModelType, api_key=None):
10
+ self.model_name: ModelType=model_name
11
+ self.api_key=api_key
12
+
13
+ def to_text(self, input_path: str | Path, sub_prompt=None, markdown=True) -> str:
14
+ result = caption_explain(input_path, model_name=self.model_name, api_key=self.api_key, sub_prompt=sub_prompt)
15
+ return chat_output_to_text(result, model_name=self.model_name, markdown=markdown)
@@ -0,0 +1,3 @@
1
+ from .service import DoclingService
2
+
3
+ __all__ = ["DoclingService"]
@@ -0,0 +1,20 @@
1
+ from pathlib import Path
2
+
3
+ from docling.document_converter import DocumentConverter
4
+
5
+ from mtt.utils.docling_utils import convert_document, document_to_markdown, document_to_text
6
+
7
+
8
+ class DoclingService:
9
+ '''docling utils 함수를 엮어서 문서/이미지를 텍스트로 변환하는 서비스.
10
+
11
+ 문서(pdf, docx, ...)는 doc2text에, 이미지는 ocr에 재사용된다.
12
+ docling이 이미지 입력에 대해서도 OCR 파이프라인을 자동으로 태우기 때문.
13
+ '''
14
+
15
+ def __init__(self, converter: DocumentConverter | None = None):
16
+ self._converter = converter or DocumentConverter()
17
+
18
+ def to_text(self, input_path: str | Path, markdown=True) -> str:
19
+ result = convert_document(self._converter, input_path)
20
+ return document_to_markdown(result) if markdown else document_to_text(result)
@@ -0,0 +1,3 @@
1
+ from .service import MeshLLMService
2
+
3
+ __all__ = ["MeshLLMService"]
@@ -0,0 +1,29 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ from mtt.utils.mesh_llm_utils import parsing_stl, parsing_obj, parsing_ply, parsing_3mf
5
+
6
+
7
+ class MeshLLMService:
8
+ '''PointNet(허깅페이스, 8bit 양자화) 기반 3D 모델 -> context vector -> projection(나중에 직접 만들거임) ->임베딩 벡터
9
+
10
+ TODO: PointNet기반 모델 로딩/추론 구현 또는 임베딩 벡터 기반 검색으로 구현할 예정.
11
+ '''
12
+
13
+ def __init__(self, **kwargs):
14
+ pass
15
+
16
+ def to_text(self, input_path: str | Path, markdown=True) -> str: #TODO: v1이고, v2에서는 pointNet기반으로 context vector를 embedding vector로 projection해서 줄듯.
17
+ _, ext = os.path.splitext(input_path)
18
+ ext = ext.lower()
19
+ if ext == ".stl":
20
+ return parsing_stl(input_path, markdown=markdown)
21
+ elif ext == ".obj":
22
+ return parsing_obj(input_path, markdown=markdown)
23
+ elif ext == ".ply":
24
+ return parsing_ply(input_path, markdown=markdown)
25
+ elif ext == ".3mf":
26
+ return parsing_3mf(input_path, markdown=markdown)
27
+ # TODO: .step/.stp, .usd/.usdz, .fbx는 PointNet으로 임베딩해서 기존 stl 등으로 구축해둔 DB에서
28
+ # 검색 후 리매핑하는 방식으로 구현 예정 (직접 파싱 대신 유사 형상 검색).
29
+ raise ValueError(f"Unreadable file or incorrect extension. input_path: {input_path}")
@@ -0,0 +1,11 @@
1
+ from typing import Literal
2
+
3
+ ModeType = Literal["caption", "ocr", "3dmodel", "doc"]
4
+
5
+ CaptionModelType=Literal["gpt-4o",
6
+ "gemini-2.5-flash",
7
+ "gemini-2.5-pro",
8
+ "gemini-3.5-flash",
9
+ "gemini-3.5-pro",
10
+ "claude-opus-4-8"
11
+ ]
File without changes