sdpy-kit 0.4.3__tar.gz → 0.4.5__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 (50) hide show
  1. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/PKG-INFO +26 -26
  2. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/README.md +25 -25
  3. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/__init__.py +1 -1
  4. sdpy_kit-0.4.5/kit/docs/__init__.py +32 -0
  5. {sdpy_kit-0.4.3/kit → sdpy_kit-0.4.5/kit/docs}/anydoc_kit.py +2 -2
  6. {sdpy_kit-0.4.3/kit → sdpy_kit-0.4.5/kit/docs}/marker_kit.py +36 -10
  7. {sdpy_kit-0.4.3/kit → sdpy_kit-0.4.5/kit/docs}/md2doc_kit.py +2 -2
  8. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/pyproject.toml +5 -5
  9. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/.gitignore +0 -0
  10. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/__init__.py +0 -0
  11. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/base_service.py +0 -0
  12. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/chat_service.py +0 -0
  13. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/embedding_service.py +0 -0
  14. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/exceptions.py +0 -0
  15. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/failover.py +0 -0
  16. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/image_service.py +0 -0
  17. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/model_builder.py +0 -0
  18. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/model_client.py +0 -0
  19. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/pool.py +0 -0
  20. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/profiles.py +0 -0
  21. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/rerank_service.py +0 -0
  22. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/runner.py +0 -0
  23. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/ai/types.py +0 -0
  24. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/common_kit.py +0 -0
  25. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/config/__init__.py +0 -0
  26. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/config/kit_config.py +0 -0
  27. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/config/log_config.py +0 -0
  28. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/crawl/__init__.py +0 -0
  29. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/crawl/article_models.py +0 -0
  30. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/crawl/web_article_kit.py +0 -0
  31. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/crawl/wx_article_kit.py +0 -0
  32. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/__init__.py +0 -0
  33. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/base_db_kit.py +0 -0
  34. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/crud.py +0 -0
  35. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/engine.py +0 -0
  36. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/exceptions.py +0 -0
  37. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/models/__init__.py +0 -0
  38. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/models/base.py +0 -0
  39. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/mysql_kit.py +0 -0
  40. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/pg_kit.py +0 -0
  41. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/query.py +0 -0
  42. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/session.py +0 -0
  43. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/sqlite_kit.py +0 -0
  44. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/db/transaction.py +0 -0
  45. {sdpy_kit-0.4.3/kit → sdpy_kit-0.4.5/kit/docs}/docx_kit.py +0 -0
  46. {sdpy_kit-0.4.3/kit → sdpy_kit-0.4.5/kit/docs}/mineru_kit.py +0 -0
  47. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/file_kit.py +0 -0
  48. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/laya_kit.py +0 -0
  49. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/license_kit.py +0 -0
  50. {sdpy_kit-0.4.3 → sdpy_kit-0.4.5}/kit/redis_kit.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sdpy-kit
3
- Version: 0.4.3
3
+ Version: 0.4.5
4
4
  Summary: SDPY Kit——统一数据库访问层(PG/MySQL/SQLite)与 AI/Redis/文件/文档/向量工具集
5
5
  Author-email: Clark <changhongyuan@126.com>
6
6
  License-Expression: MIT
@@ -77,7 +77,7 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
77
77
 
78
78
  - **统一数据库访问层**:PostgreSQL / MySQL / SQLite,三个 Kit API 完全一致,切换数据库只改一行 import;
79
79
  - **AI 多模型服务池**:chat / embedding / rerank / image 四类能力,多厂商候选链 + 故障自动转移;
80
- - **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
80
+ - **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images/) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
81
81
 
82
82
  > 要求 Python 3.13+
83
83
 
@@ -91,11 +91,11 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
91
91
  | `kit.redis_kit` | `RedisKit` | Redis string / hash / list / set / zset | `redis` |
92
92
  | `kit.file_kit` | `FileKit` | 文件与目录读写、移动、遍历 | 无 |
93
93
  | `kit.common_kit` | `CommonKit` | 雪花 ID、时间戳 ID、时间格式化 | 无 |
94
- | `kit.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
95
- | `kit.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
96
- | `kit.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
97
- | `kit.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
98
- | `kit.marker_kit` | `MarkerKit` | 本地文档解析(PDF / 图片 / Office → Markdown + Images) | `marker` |
94
+ | `kit.docs.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
95
+ | `kit.docs.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
96
+ | `kit.docs.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
97
+ | `kit.docs.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
98
+ | `kit.docs.marker_kit` | `MarkerKit` | 本地文档解析(PDF / 图片 / Office → Markdown + Images) | `marker` |
99
99
  | `kit.laya_kit` | `LayaKit` | 类型化决策:choice / score / noul,返回判断结果 + 置信度 | `laya` |
100
100
  | `kit.crawl.article_models` | `ArticleInfo` / `ArticleResult` / `SavedOutput` 等 | 文章抓取通用模型(两 `*ArticleKit` 共用,含 `reason` 分类与非致命 `warnings`) | 无 |
101
101
  | `kit.crawl.wx_article_kit` | `WxArticleKit` | 微信公众号文章 → Markdown + 图片转存 | 无 |
@@ -180,7 +180,7 @@ SQLITE_DB_PATH=./data/sqlite.db
180
180
 
181
181
  ### 环境变量 ↔ 能力对照表
182
182
 
183
- > 表中未出现的模块(`kit.crawl.article_models`、`kit.common_kit`、`kit.docx_kit`、`kit.md2doc_kit`、`kit.crawl.wx_article_kit`、`kit.crawl.web_article_kit`)不读取任何环境变量。
183
+ > 表中未出现的模块(`kit.crawl.article_models`、`kit.common_kit`、`kit.docs.docx_kit`、`kit.docs.md2doc_kit`、`kit.crawl.wx_article_kit`、`kit.crawl.web_article_kit`)不读取任何环境变量。
184
184
 
185
185
  **基础与日志**(影响 `kit.config` 及所有模块的日志输出)
186
186
 
@@ -231,7 +231,7 @@ SQLITE_DB_PATH=./data/sqlite.db
231
231
  | `KIT_AI_CHAIN_TIMEOUT` | 未设置 | 全局整链预算(秒)= 门面同步等待上限。⚠ **不是 `Settings` 字段**,由代码直读 `os.environ`,无类型/范围校验,非法值仅告警后回退 |
232
232
  | *(密钥,变量名由档案决定)* | 无 | 名字写在 `ai_models.json` 各档案的 `api_key` 字段(如 `SILICONFLOW_API_KEY`),值放 `.env` 或系统环境变量。未配置的档案会被剔除出候选链;该类型全部未配置则调用失败 |
233
233
 
234
- **MinerU** → `kit.mineru_kit`
234
+ **MinerU** → `kit.docs.mineru_kit`
235
235
 
236
236
  | 环境变量 | 默认值 | 作用 |
237
237
  |----------|--------|------|
@@ -242,7 +242,7 @@ SQLITE_DB_PATH=./data/sqlite.db
242
242
  | `MINERU_POLL_INTERVAL` | `2.0`(≥0.5) | 任务轮询间隔 |
243
243
  | `MINERU_MAX_WAIT` | `600`(≥10) | 轮询总超时,超时抛 `MinerUError` |
244
244
 
245
- **Marker** → `kit.marker_kit`
245
+ **Marker** → `kit.docs.marker_kit`
246
246
 
247
247
  | 环境变量 | 默认值 | 作用 |
248
248
  |----------|--------|------|
@@ -265,7 +265,7 @@ SQLITE_DB_PATH=./data/sqlite.db
265
265
  > `LAYA_HF_*` 同样由 kit 在**导入 laya 之前**经 `os.environ.setdefault` 应用,不覆盖显式配置;
266
266
  > `LAYA_MODEL` / `LAYA_DEVICE` 由 `Settings` 读取(进程内缓存,改后需重启进程)。
267
267
 
268
- **云 OCR**(任何 `ocr="hosted"` 的转换)→ `kit.anydoc_kit`
268
+ **云 OCR**(任何 `ocr="hosted"` 的转换)→ `kit.docs.anydoc_kit`
269
269
 
270
270
  | 环境变量 | 默认值 | 作用 |
271
271
  |----------|--------|------|
@@ -295,7 +295,7 @@ SQLITE_DB_PATH=./data/sqlite.db
295
295
  | 改动内容 | 生效时机 |
296
296
  |----------|----------|
297
297
  | `LOG_*`、`DB_*`、`MYSQL_*`、`REDIS_*`、`FILE_STORAGE_ROOT`、`MINERU_*`、`MARKER_MODE` | `get_settings()` 带 `lru_cache`,进程内首次读取后固定 → **重启进程**(或调用 `AI.reload_config()`,它会顺带清空该缓存) |
298
- | `MARKER_HF_ENDPOINT` / `MARKER_HF_DISABLE_XET` / `MARKER_LLAMA_CPP_BINARY` | 仅在 `import kit.marker_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
298
+ | `MARKER_HF_ENDPOINT` / `MARKER_HF_DISABLE_XET` / `MARKER_LLAMA_CPP_BINARY` | 仅在 `import kit.docs.marker_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
299
299
  | `LAYA_HF_ENDPOINT` / `LAYA_HF_DISABLE_XET` | 仅在 `import kit.laya_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
300
300
  | AI 密钥写在 `.env` 里 | `.env` 只在加载档案时注入一次 → 重启,或 `AI.reload_config(reload_file=True)` |
301
301
  | AI 密钥由自己写入 `os.environ` | `AI.reload_config()`(默认 `reload_file=False`,只重读 `os.environ`) |
@@ -849,12 +849,12 @@ CommonKit.format_current_time("yyyy-MM-dd")
849
849
 
850
850
  ---
851
851
 
852
- ## kit.anydoc_kit —— 文档转 Markdown
852
+ ## kit.docs.anydoc_kit —— 文档转 Markdown
853
853
 
854
854
  安装:`pip install "sdpy-kit[anydoc]"`(支持 `.doc .docx .ppt .pptx .xls .xlsx .csv .pdf`)
855
855
 
856
856
  ```python
857
- from kit.anydoc_kit import AnyDocKit
857
+ from kit.docs.anydoc_kit import AnyDocKit
858
858
 
859
859
  markdown = AnyDocKit.convert_to_md("report.docx") # 直接转换,失败抛异常
860
860
  result = AnyDocKit.convert("report.pdf") # 安全转换,异常封装为结果对象
@@ -878,12 +878,12 @@ md = AnyDocKit.convert_to_md("scan.pdf", ocr="hosted") # 需 FIRECRAWL_API_KEY
878
878
 
879
879
  ---
880
880
 
881
- ## kit.docx_kit —— Word 模板动态填充
881
+ ## kit.docs.docx_kit —— Word 模板动态填充
882
882
 
883
883
  安装:`pip install "sdpy-kit[docx]"`
884
884
 
885
885
  ```python
886
- from kit.docx_kit import DocxKit, DocxReport, DocxSection, DocxParagraph, DocxTable
886
+ from kit.docs.docx_kit import DocxKit, DocxReport, DocxSection, DocxParagraph, DocxTable
887
887
 
888
888
  DocxKit.create_template("templates/report.docx", title="{{ title }}") # 生成模板骨架
889
889
  DocxKit.unify_font("templates/report.docx", font_name="宋体")
@@ -917,12 +917,12 @@ DocxKit.render("templates/report.docx", "out/report.docx", report)
917
917
 
918
918
  ---
919
919
 
920
- ## kit.md2doc_kit —— Markdown 转 Word / PDF / HTML
920
+ ## kit.docs.md2doc_kit —— Markdown 转 Word / PDF / HTML
921
921
 
922
922
  安装:`pip install "sdpy-kit[md2doc]"`(PDF 需系统已安装 `mainfont` 指定字体,默认 `SimSun`)
923
923
 
924
924
  ```python
925
- from kit.md2doc_kit import Md2DocKit
925
+ from kit.docs.md2doc_kit import Md2DocKit
926
926
 
927
927
  Md2DocKit.convert_md_to_docx("report.md", "out.docx", generate_toc=True)
928
928
  Md2DocKit.convert_md_to_html("report.md", title="项目报告")
@@ -939,12 +939,12 @@ Md2DocKit.convert_md_to_pdf("report.md", mainfont="KaiTi")
939
939
 
940
940
  ---
941
941
 
942
- ## kit.mineru_kit —— MinerU 文档解析
942
+ ## kit.docs.mineru_kit —— MinerU 文档解析
943
943
 
944
944
  安装:`pip install "sdpy-kit[mineru]"`(精准解析需 `MINERU_API_KEY`,Agent 轻量解析免登录)
945
945
 
946
946
  ```python
947
- from kit.mineru_kit import MinerUKit
947
+ from kit.docs.mineru_kit import MinerUKit
948
948
 
949
949
  # 精准解析:公网 URL / 本地文件
950
950
  result = MinerUKit.parse_url("https://cdn-mineru.openxlab.org.cn/demo/example.pdf", model_version="vlm")
@@ -971,15 +971,15 @@ if r.state == "done":
971
971
 
972
972
  ---
973
973
 
974
- ## kit.marker_kit —— 本地文档解析(Markdown + Images)
974
+ ## kit.docs.marker_kit —— 本地文档解析(Markdown + Images)
975
975
 
976
976
  安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf[full]`,含 torch 等 80+ 包,体积较大)
977
977
 
978
978
  ```python
979
- from kit.marker_kit import MarkerKit
979
+ from kit.docs.marker_kit import MarkerKit
980
980
 
981
- # 落盘 md + images(推荐):源文件同目录下建同名子目录
982
- md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + 图片
981
+ # 落盘 md + images/(推荐):源文件同目录下建同名子目录
982
+ md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + report/images/
983
983
  md_path = MarkerKit.convert_to_dir("report.pdf", "out/doc") # 指定产物目录
984
984
 
985
985
  # 只取 Markdown 文本(图片不落盘)
@@ -1000,11 +1000,11 @@ MarkerKit.shutdown() # 释放模型与推理服务(幂等)
1000
1000
  |------|------|
1001
1001
  | `is_supported(file_path) -> bool` | 扩展名白名单(pdf / 图片 / docx / pptx / xlsx / html / epub) |
1002
1002
  | `convert_to_md(file_path, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None) -> str` | 解析并返回 Markdown 文本(图片不落盘) |
1003
- | `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + images,返回 md 绝对路径 |
1003
+ | `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + `images/`,返回 md 绝对路径 |
1004
1004
  | `convert(src_path, output_dir=None, *, ...) -> MarkerResult` | 安全版:失败封装为 `MarkerResult`,不抛异常 |
1005
1005
  | `shutdown() -> None` | 释放模型与共享推理服务(幂等) |
1006
1006
 
1007
- > 产物:`<output_dir>/<源文件名>.md` + 图片文件(md 内相对路径引用),**不生成** `_meta.json`。
1007
+ > 产物:`<output_dir>/<源文件名>.md` + `<output_dir>/images/`(md 内以 `images/<文件名>` 相对引用;无图片不建空目录),**不生成** `_meta.json`。
1008
1008
  > 结果类型:`MarkerResult`(`success` / `markdown` / `file_path` / `output_dir` / `md_path` / `image_paths` / `page_count` / `error`);异常:`MarkerError`。
1009
1009
  > `mode` 缺省时不写入配置,交由 marker 按设备自动选择;首次使用会下载模型权重(默认走 `MARKER_HF_ENDPOINT` 镜像)。
1010
1010
  > 非 NVIDIA 平台完整 VLM 能力(公式 / 扫描页 OCR)需 llama.cpp 的 `llama-server`,否则用 `disable_ocr=True` 跳过。
@@ -4,7 +4,7 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
4
4
 
5
5
  - **统一数据库访问层**:PostgreSQL / MySQL / SQLite,三个 Kit API 完全一致,切换数据库只改一行 import;
6
6
  - **AI 多模型服务池**:chat / embedding / rerank / image 四类能力,多厂商候选链 + 故障自动转移;
7
- - **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
7
+ - **工具集**:Redis / 文件 / 雪花 ID / 文档互转 / Word 模板填充 / MinerU 解析 / Marker 本地解析(md + images/) / Laya 类型化决策 / 微信公众号文章抓取存储 / 通用网页文章抓取存储。
8
8
 
9
9
  > 要求 Python 3.13+
10
10
 
@@ -18,11 +18,11 @@ SDPY 统一工具集(Kit 体系),供 Python 项目开箱即用:
18
18
  | `kit.redis_kit` | `RedisKit` | Redis string / hash / list / set / zset | `redis` |
19
19
  | `kit.file_kit` | `FileKit` | 文件与目录读写、移动、遍历 | 无 |
20
20
  | `kit.common_kit` | `CommonKit` | 雪花 ID、时间戳 ID、时间格式化 | 无 |
21
- | `kit.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
22
- | `kit.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
23
- | `kit.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
24
- | `kit.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
25
- | `kit.marker_kit` | `MarkerKit` | 本地文档解析(PDF / 图片 / Office → Markdown + Images) | `marker` |
21
+ | `kit.docs.anydoc_kit` | `AnyDocKit` | docx / pdf / xlsx 等 → Markdown | `anydoc` |
22
+ | `kit.docs.docx_kit` | `DocxKit` | Word 模板动态填充(章节 / 列表 / 表格) | `docx` |
23
+ | `kit.docs.md2doc_kit` | `Md2DocKit` | Markdown → Word / PDF / HTML | `md2doc` |
24
+ | `kit.docs.mineru_kit` | `MinerUKit` | MinerU 文档解析(精准 + Agent 轻量) | `mineru` |
25
+ | `kit.docs.marker_kit` | `MarkerKit` | 本地文档解析(PDF / 图片 / Office → Markdown + Images) | `marker` |
26
26
  | `kit.laya_kit` | `LayaKit` | 类型化决策:choice / score / noul,返回判断结果 + 置信度 | `laya` |
27
27
  | `kit.crawl.article_models` | `ArticleInfo` / `ArticleResult` / `SavedOutput` 等 | 文章抓取通用模型(两 `*ArticleKit` 共用,含 `reason` 分类与非致命 `warnings`) | 无 |
28
28
  | `kit.crawl.wx_article_kit` | `WxArticleKit` | 微信公众号文章 → Markdown + 图片转存 | 无 |
@@ -107,7 +107,7 @@ SQLITE_DB_PATH=./data/sqlite.db
107
107
 
108
108
  ### 环境变量 ↔ 能力对照表
109
109
 
110
- > 表中未出现的模块(`kit.crawl.article_models`、`kit.common_kit`、`kit.docx_kit`、`kit.md2doc_kit`、`kit.crawl.wx_article_kit`、`kit.crawl.web_article_kit`)不读取任何环境变量。
110
+ > 表中未出现的模块(`kit.crawl.article_models`、`kit.common_kit`、`kit.docs.docx_kit`、`kit.docs.md2doc_kit`、`kit.crawl.wx_article_kit`、`kit.crawl.web_article_kit`)不读取任何环境变量。
111
111
 
112
112
  **基础与日志**(影响 `kit.config` 及所有模块的日志输出)
113
113
 
@@ -158,7 +158,7 @@ SQLITE_DB_PATH=./data/sqlite.db
158
158
  | `KIT_AI_CHAIN_TIMEOUT` | 未设置 | 全局整链预算(秒)= 门面同步等待上限。⚠ **不是 `Settings` 字段**,由代码直读 `os.environ`,无类型/范围校验,非法值仅告警后回退 |
159
159
  | *(密钥,变量名由档案决定)* | 无 | 名字写在 `ai_models.json` 各档案的 `api_key` 字段(如 `SILICONFLOW_API_KEY`),值放 `.env` 或系统环境变量。未配置的档案会被剔除出候选链;该类型全部未配置则调用失败 |
160
160
 
161
- **MinerU** → `kit.mineru_kit`
161
+ **MinerU** → `kit.docs.mineru_kit`
162
162
 
163
163
  | 环境变量 | 默认值 | 作用 |
164
164
  |----------|--------|------|
@@ -169,7 +169,7 @@ SQLITE_DB_PATH=./data/sqlite.db
169
169
  | `MINERU_POLL_INTERVAL` | `2.0`(≥0.5) | 任务轮询间隔 |
170
170
  | `MINERU_MAX_WAIT` | `600`(≥10) | 轮询总超时,超时抛 `MinerUError` |
171
171
 
172
- **Marker** → `kit.marker_kit`
172
+ **Marker** → `kit.docs.marker_kit`
173
173
 
174
174
  | 环境变量 | 默认值 | 作用 |
175
175
  |----------|--------|------|
@@ -192,7 +192,7 @@ SQLITE_DB_PATH=./data/sqlite.db
192
192
  > `LAYA_HF_*` 同样由 kit 在**导入 laya 之前**经 `os.environ.setdefault` 应用,不覆盖显式配置;
193
193
  > `LAYA_MODEL` / `LAYA_DEVICE` 由 `Settings` 读取(进程内缓存,改后需重启进程)。
194
194
 
195
- **云 OCR**(任何 `ocr="hosted"` 的转换)→ `kit.anydoc_kit`
195
+ **云 OCR**(任何 `ocr="hosted"` 的转换)→ `kit.docs.anydoc_kit`
196
196
 
197
197
  | 环境变量 | 默认值 | 作用 |
198
198
  |----------|--------|------|
@@ -222,7 +222,7 @@ SQLITE_DB_PATH=./data/sqlite.db
222
222
  | 改动内容 | 生效时机 |
223
223
  |----------|----------|
224
224
  | `LOG_*`、`DB_*`、`MYSQL_*`、`REDIS_*`、`FILE_STORAGE_ROOT`、`MINERU_*`、`MARKER_MODE` | `get_settings()` 带 `lru_cache`,进程内首次读取后固定 → **重启进程**(或调用 `AI.reload_config()`,它会顺带清空该缓存) |
225
- | `MARKER_HF_ENDPOINT` / `MARKER_HF_DISABLE_XET` / `MARKER_LLAMA_CPP_BINARY` | 仅在 `import kit.marker_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
225
+ | `MARKER_HF_ENDPOINT` / `MARKER_HF_DISABLE_XET` / `MARKER_LLAMA_CPP_BINARY` | 仅在 `import kit.docs.marker_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
226
226
  | `LAYA_HF_ENDPOINT` / `LAYA_HF_DISABLE_XET` | 仅在 `import kit.laya_kit` 时经 `os.environ.setdefault` 应用 → 改动需**重启进程**重新导入模块 |
227
227
  | AI 密钥写在 `.env` 里 | `.env` 只在加载档案时注入一次 → 重启,或 `AI.reload_config(reload_file=True)` |
228
228
  | AI 密钥由自己写入 `os.environ` | `AI.reload_config()`(默认 `reload_file=False`,只重读 `os.environ`) |
@@ -776,12 +776,12 @@ CommonKit.format_current_time("yyyy-MM-dd")
776
776
 
777
777
  ---
778
778
 
779
- ## kit.anydoc_kit —— 文档转 Markdown
779
+ ## kit.docs.anydoc_kit —— 文档转 Markdown
780
780
 
781
781
  安装:`pip install "sdpy-kit[anydoc]"`(支持 `.doc .docx .ppt .pptx .xls .xlsx .csv .pdf`)
782
782
 
783
783
  ```python
784
- from kit.anydoc_kit import AnyDocKit
784
+ from kit.docs.anydoc_kit import AnyDocKit
785
785
 
786
786
  markdown = AnyDocKit.convert_to_md("report.docx") # 直接转换,失败抛异常
787
787
  result = AnyDocKit.convert("report.pdf") # 安全转换,异常封装为结果对象
@@ -805,12 +805,12 @@ md = AnyDocKit.convert_to_md("scan.pdf", ocr="hosted") # 需 FIRECRAWL_API_KEY
805
805
 
806
806
  ---
807
807
 
808
- ## kit.docx_kit —— Word 模板动态填充
808
+ ## kit.docs.docx_kit —— Word 模板动态填充
809
809
 
810
810
  安装:`pip install "sdpy-kit[docx]"`
811
811
 
812
812
  ```python
813
- from kit.docx_kit import DocxKit, DocxReport, DocxSection, DocxParagraph, DocxTable
813
+ from kit.docs.docx_kit import DocxKit, DocxReport, DocxSection, DocxParagraph, DocxTable
814
814
 
815
815
  DocxKit.create_template("templates/report.docx", title="{{ title }}") # 生成模板骨架
816
816
  DocxKit.unify_font("templates/report.docx", font_name="宋体")
@@ -844,12 +844,12 @@ DocxKit.render("templates/report.docx", "out/report.docx", report)
844
844
 
845
845
  ---
846
846
 
847
- ## kit.md2doc_kit —— Markdown 转 Word / PDF / HTML
847
+ ## kit.docs.md2doc_kit —— Markdown 转 Word / PDF / HTML
848
848
 
849
849
  安装:`pip install "sdpy-kit[md2doc]"`(PDF 需系统已安装 `mainfont` 指定字体,默认 `SimSun`)
850
850
 
851
851
  ```python
852
- from kit.md2doc_kit import Md2DocKit
852
+ from kit.docs.md2doc_kit import Md2DocKit
853
853
 
854
854
  Md2DocKit.convert_md_to_docx("report.md", "out.docx", generate_toc=True)
855
855
  Md2DocKit.convert_md_to_html("report.md", title="项目报告")
@@ -866,12 +866,12 @@ Md2DocKit.convert_md_to_pdf("report.md", mainfont="KaiTi")
866
866
 
867
867
  ---
868
868
 
869
- ## kit.mineru_kit —— MinerU 文档解析
869
+ ## kit.docs.mineru_kit —— MinerU 文档解析
870
870
 
871
871
  安装:`pip install "sdpy-kit[mineru]"`(精准解析需 `MINERU_API_KEY`,Agent 轻量解析免登录)
872
872
 
873
873
  ```python
874
- from kit.mineru_kit import MinerUKit
874
+ from kit.docs.mineru_kit import MinerUKit
875
875
 
876
876
  # 精准解析:公网 URL / 本地文件
877
877
  result = MinerUKit.parse_url("https://cdn-mineru.openxlab.org.cn/demo/example.pdf", model_version="vlm")
@@ -898,15 +898,15 @@ if r.state == "done":
898
898
 
899
899
  ---
900
900
 
901
- ## kit.marker_kit —— 本地文档解析(Markdown + Images)
901
+ ## kit.docs.marker_kit —— 本地文档解析(Markdown + Images)
902
902
 
903
903
  安装:`pip install "sdpy-kit[marker]"`(依赖 `marker-pdf[full]`,含 torch 等 80+ 包,体积较大)
904
904
 
905
905
  ```python
906
- from kit.marker_kit import MarkerKit
906
+ from kit.docs.marker_kit import MarkerKit
907
907
 
908
- # 落盘 md + images(推荐):源文件同目录下建同名子目录
909
- md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + 图片
908
+ # 落盘 md + images/(推荐):源文件同目录下建同名子目录
909
+ md_path = MarkerKit.convert_to_dir("report.pdf") # -> report/report.md + report/images/
910
910
  md_path = MarkerKit.convert_to_dir("report.pdf", "out/doc") # 指定产物目录
911
911
 
912
912
  # 只取 Markdown 文本(图片不落盘)
@@ -927,11 +927,11 @@ MarkerKit.shutdown() # 释放模型与推理服务(幂等)
927
927
  |------|------|
928
928
  | `is_supported(file_path) -> bool` | 扩展名白名单(pdf / 图片 / docx / pptx / xlsx / html / epub) |
929
929
  | `convert_to_md(file_path, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None) -> str` | 解析并返回 Markdown 文本(图片不落盘) |
930
- | `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + images,返回 md 绝对路径 |
930
+ | `convert_to_dir(src_path, output_dir=None, *, mode=None, force_ocr=None, disable_ocr=None, page_range=None, extract_images=True) -> str` | 解析并落盘 md + `images/`,返回 md 绝对路径 |
931
931
  | `convert(src_path, output_dir=None, *, ...) -> MarkerResult` | 安全版:失败封装为 `MarkerResult`,不抛异常 |
932
932
  | `shutdown() -> None` | 释放模型与共享推理服务(幂等) |
933
933
 
934
- > 产物:`<output_dir>/<源文件名>.md` + 图片文件(md 内相对路径引用),**不生成** `_meta.json`。
934
+ > 产物:`<output_dir>/<源文件名>.md` + `<output_dir>/images/`(md 内以 `images/<文件名>` 相对引用;无图片不建空目录),**不生成** `_meta.json`。
935
935
  > 结果类型:`MarkerResult`(`success` / `markdown` / `file_path` / `output_dir` / `md_path` / `image_paths` / `page_count` / `error`);异常:`MarkerError`。
936
936
  > `mode` 缺省时不写入配置,交由 marker 按设备自动选择;首次使用会下载模型权重(默认走 `MARKER_HF_ENDPOINT` 镜像)。
937
937
  > 非 NVIDIA 平台完整 VLM 能力(公式 / 扫描页 OCR)需 llama.cpp 的 `llama-server`,否则用 `disable_ocr=True` 跳过。
@@ -23,7 +23,7 @@ Author: Clark Chang
23
23
  数据库访问通过 kit.db 子包提供(基于 SQLModel)。
24
24
  """
25
25
 
26
- __version__ = "0.4.3"
26
+ __version__ = "0.4.5"
27
27
 
28
28
  from kit.db import (
29
29
  MYSQL,
@@ -0,0 +1,32 @@
1
+ """
2
+ Copyright (c) 2021-2026 Clark Chang. All Rights Reserved.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+
16
+ Project: sdpy
17
+ Author: Clark Chang
18
+ """
19
+
20
+ # date: 2026-10-16
21
+ """文档格式转换子包——文档解析 / 渲染 / 模板填充工具集
22
+
23
+ 成员(均按需 import,各自绑定独立 extras,缺依赖时模块顶层报错并提示安装命令):
24
+ - anydoc_kit: AnyDocKit 文档转 Markdown(firecrawl-anydoc,extra: anydoc)
25
+ - md2doc_kit: Md2DocKit Markdown 转 Word/PDF/HTML(pimd,extra: md2doc)
26
+ - docx_kit: DocxKit Word 模板动态填充(docxtpl,extra: docx)
27
+ - mineru_kit: MinerUKit MinerU 文档解析 API(requests,extra: mineru)
28
+ - marker_kit: MarkerKit Marker 本地文档解析(marker-pdf,extra: marker)
29
+
30
+ 本 __init__ 不导入任何成员:五个模块均携带重型可选依赖,保持
31
+ `import kit.docs` 在基础安装下零成本可用(对齐 kit.crawl 先例)。
32
+ """
@@ -22,7 +22,7 @@ Author: Clark Chang
22
22
 
23
23
  本模块封装 firecrawl-anydoc(pip 安装名 firecrawl-anydoc,import 名 anydoc),
24
24
  将 Word、PowerPoint、Excel、CSV、PDF 格式统一转为 GitHub-Flavored Markdown;
25
- Markdown → Word/HTML/PDF 的反向转换见 kit.md2doc_kit(Md2DocKit)。
25
+ Markdown → Word/HTML/PDF 的反向转换见 kit.docs.md2doc_kit(Md2DocKit)。
26
26
 
27
27
  设计要点:
28
28
  - 全部使用静态方法提供服务,无内部状态。
@@ -183,7 +183,7 @@ class AnyDocKit:
183
183
  # 5. 字节内容转换(无需落盘)
184
184
  md = AnyDocKit.convert_bytes_to_md(file_bytes, "csv")
185
185
 
186
- Markdown → Word/PDF/HTML 的反向转换见 kit.md2doc_kit(Md2DocKit)。
186
+ Markdown → Word/PDF/HTML 的反向转换见 kit.docs.md2doc_kit(Md2DocKit)。
187
187
 
188
188
  可与 FileKit 组合使用以访问 FILE_STORAGE_ROOT 下的相对路径文件:
189
189
  full_path = FileKit.get_full_path("docs/report.docx")
@@ -22,9 +22,9 @@ Author: Clark Chang
22
22
 
23
23
  本模块基于 marker-pdf(Marker v2.x,https://github.com/datalab-to/marker),
24
24
  在本地解析 PDF / 图片 / Office / HTML / EPUB,输出 GitHub-Flavored Markdown
25
- 并提取图片,产物形态对齐 kit.mineru_kit 的「md + images」。
25
+ 并提取图片,产物形态为「md + images/」一层(kit 文档解析类工具的统一契约)。
26
26
 
27
- 与 kit.anydoc_kit 的分工:
27
+ 与 kit.docs.anydoc_kit 的分工:
28
28
  - AnyDocKit:轻量文本转换(firecrawl-anydoc),只产出 Markdown 文本;
29
29
  - MarkerKit:本地模型解析,产出 md + 图片,质量更高但依赖重(torch 等)。
30
30
 
@@ -125,7 +125,7 @@ class MarkerResult:
125
125
  file_path: 源文件绝对路径
126
126
  output_dir: 产物目录绝对路径;未落盘时为 None
127
127
  md_path: 落盘的 Markdown 文件绝对路径;未落盘时为 None
128
- image_paths: 落盘的图片文件绝对路径元组
128
+ image_paths: 落盘的图片文件绝对路径元组(位于 `<output_dir>/images/`)
129
129
  page_count: 文档页数,未知为 None
130
130
  error: 失败原因描述(异常类型与信息),成功时为 None
131
131
  """
@@ -143,8 +143,8 @@ class MarkerResult:
143
143
  class MarkerKit:
144
144
  """Marker 本地文档解析工具类,将文档转为 Markdown + Images
145
145
 
146
- 支持 PDF、图片、Office(docx/pptx/xlsx)、HTML、EPUB,产物形态对齐
147
- kit.mineru_kit(md + 图片落盘于同一目录,md 以相对路径引用图片)。
146
+ 支持 PDF、图片、Office(docx/pptx/xlsx)、HTML、EPUB,产物形态为
147
+ 「md + images/」一层(md 以 `images/<文件名>` 相对路径引用图片)。
148
148
 
149
149
  使用前安装可选依赖::
150
150
 
@@ -322,7 +322,25 @@ class MarkerKit:
322
322
  return Path(output_dir).resolve()
323
323
 
324
324
  @staticmethod
325
+ def _localize_image_refs(markdown: str, mapping: dict[str, str]) -> str:
326
+ """把 md 中的裸图片文件名引用改写为 `images/` 相对路径
327
+
328
+ Args:
329
+ markdown: marker 输出的 Markdown 原文
330
+ mapping: 原文件名 → 改写后的相对路径(如 `_page_0_Figure_1.jpeg`
331
+ → `images/_page_0_Figure_1.jpeg`)
332
+
333
+ Returns:
334
+ str: 改写后的 Markdown
335
+ """
336
+ for original, rel in mapping.items():
337
+ markdown = markdown.replace(f"]({original})", f"]({rel})")
338
+ markdown = markdown.replace(f'src="{original}"', f'src="{rel}"')
339
+ return markdown
340
+
341
+ @classmethod
325
342
  def _write_outputs(
343
+ cls,
326
344
  src: Path,
327
345
  out_dir: Path,
328
346
  markdown: str,
@@ -332,18 +350,25 @@ class MarkerKit:
332
350
  ) -> tuple[str, tuple[str, ...]]:
333
351
  """落盘 Markdown 与图片,返回 (md 路径, 图片路径元组)
334
352
 
353
+ 产物为 `<out_dir>/<源文件名>.md` + `<out_dir>/images/` 图片目录,
354
+ md 内以 `images/<文件名>` 相对引用;无图片时不创建空 `images/`。
335
355
  图片名取 basename 防路径穿越;统一转 RGB 后再存(RGBA 存 JPEG 会失败)。
336
356
  """
337
357
  out_dir.mkdir(parents=True, exist_ok=True)
338
- md_path = out_dir / f"{src.stem}.md"
339
- md_path.write_text(markdown, encoding="utf-8")
340
-
341
358
  image_paths: list[str] = []
342
359
  if extract_images:
360
+ images_dir = out_dir / "images"
361
+ mapping: dict[str, str] = {}
343
362
  for name, image in images.items():
344
- target = out_dir / Path(name).name
363
+ target = images_dir / Path(name).name
364
+ target.parent.mkdir(parents=True, exist_ok=True)
345
365
  image.convert("RGB").save(target)
366
+ mapping[target.name] = f"images/{target.name}"
346
367
  image_paths.append(str(target))
368
+ markdown = cls._localize_image_refs(markdown, mapping)
369
+
370
+ md_path = out_dir / f"{src.stem}.md"
371
+ md_path.write_text(markdown, encoding="utf-8")
347
372
  return str(md_path), tuple(image_paths)
348
373
 
349
374
  # ------------------------------------------------------------------
@@ -410,7 +435,8 @@ class MarkerKit:
410
435
  ) -> str:
411
436
  """解析文档并将 Markdown + 图片落盘到目录
412
437
 
413
- 产物写入 output_dir:`<源文件名>.md` 与若干图片文件(md 以相对路径引用)。
438
+ 产物写入 output_dir:`<源文件名>.md` 与 `images/` 图片目录(md 内以
439
+ `images/<文件名>` 相对路径引用);无图片时不创建空 `images/`。
414
440
  不生成 marker 默认的 `_meta.json`。
415
441
 
416
442
  Args:
@@ -22,7 +22,7 @@ Author: Clark Chang
22
22
 
23
23
  本模块基于 PiMD(pimd >= 2.2.5)将 Markdown 转换为 Word(.docx)与独立
24
24
  HTML;PDF 由本模块内嵌的 fpdf2 渲染器直接生成,保证中文与表格完整。
25
- 各类文档(Office/PDF)→ Markdown 的正向解析见 kit.anydoc_kit(AnyDocKit)。
25
+ 各类文档(Office/PDF)→ Markdown 的正向解析见 kit.docs.anydoc_kit(AnyDocKit)。
26
26
 
27
27
  设计要点:
28
28
  - 全部使用静态方法提供服务,无内部状态;PiMD 转换引擎为模块级单例,按进程
@@ -1056,7 +1056,7 @@ class Md2DocKit:
1056
1056
  convert_md_to_pdf 方法说明);需要 PDF 时优先用 convert_md_to_html
1057
1057
  后在浏览器中打印/另存 PDF,或 convert_md_to_docx 后在 Word 中另存 PDF。
1058
1058
 
1059
- 各类文档(Office/PDF)→ Markdown 的正向解析见 kit.anydoc_kit(AnyDocKit)。
1059
+ 各类文档(Office/PDF)→ Markdown 的正向解析见 kit.docs.anydoc_kit(AnyDocKit)。
1060
1060
  可与 FileKit 组合使用以访问 FILE_STORAGE_ROOT 下的相对路径文件:
1061
1061
  full_path = FileKit.get_full_path("docs/report.md")
1062
1062
  Md2DocKit.convert_md_to_html(full_path)
@@ -47,11 +47,11 @@ dynamic = ["version"]
47
47
  # sqliteai → sqlite_kit 向量方法(numpy/sqliteai-vector,向量扩展)
48
48
  # redis → redis_kit
49
49
  # ai → kit/ai 服务池(httpx;dotenv 由 kit.ai 直接 import,故显式声明)
50
- # md2doc → md2doc_kit(pimd/markdown-it-py,fpdf2;extra 名与模块名一致)
51
- # anydoc → anydoc_kit(firecrawl-anydoc + pikepdf,显式声明)
52
- # docx → docx_kit(docxtpl + python-docx,模板动态填充)
53
- # mineru → mineru_kit(requests)
54
- # marker → marker_kit(marker-pdf[full],本地模型解析 PDF→Markdown+Images)
50
+ # md2doc → kit.docs.md2doc_kit(pimd/markdown-it-py,fpdf2;extra 名沿用模块族名)
51
+ # anydoc → kit.docs.anydoc_kit(firecrawl-anydoc + pikepdf,显式声明)
52
+ # docx → kit.docs.docx_kit(docxtpl + python-docx,模板动态填充)
53
+ # mineru → kit.docs.mineru_kit(requests)
54
+ # marker → kit.docs.marker_kit(marker-pdf[full],本地模型解析 PDF→Markdown+Images)
55
55
  # laya → laya_kit(laya + torch,本地类型化决策引擎 choice/score/noul)
56
56
  # web-article → crawl/web_article_kit(trafilatura,通用网页文章抓取转存)
57
57
  # 基础版 = config/log + kit.db 核心,SQLite 常规操作用标准库 sqlite3,零额外依赖。
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes