Metadata-Version: 2.5
Name: zleap_parser
Version: 0.3.0
Summary: zleap 文档解析 SDK：多格式文件/URL 解析为 knowledge-only OCTX 归档
Author: zleap
License-Expression: MIT
License-File: LICENSE
License-File: LICENSES/Apache-2.0.txt
Keywords: document,knowledge,markdown,octx,parser
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Text Processing :: Markup
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: beautifulsoup4>=4.12
Requires-Dist: camoufox==0.5.8
Requires-Dist: octx>=0.1.6
Requires-Dist: openai<2,>=1.68
Requires-Dist: playwright>=1.40
Requires-Dist: pycryptodome>=3.19
Requires-Dist: pydantic<3,>=2.13.4
Requires-Dist: tzdata>=2024.1; sys_platform == 'win32'
Requires-Dist: uuid6>=2025.0.1
Provides-Extra: all-databases
Requires-Dist: elasticsearch<10,>=8.0; extra == 'all-databases'
Requires-Dist: psycopg2-binary>=2.9; extra == 'all-databases'
Requires-Dist: pymongo>=4.6; extra == 'all-databases'
Requires-Dist: pymysql>=1.1; extra == 'all-databases'
Requires-Dist: sqlalchemy>=2.0; extra == 'all-databases'
Provides-Extra: bigdb
Requires-Dist: clickhouse-connect>=0.8; extra == 'bigdb'
Requires-Dist: psycopg2-binary>=2.9; extra == 'bigdb'
Requires-Dist: pymysql>=1.1; extra == 'bigdb'
Provides-Extra: bigdb-clickhouse
Requires-Dist: clickhouse-connect>=0.8; extra == 'bigdb-clickhouse'
Provides-Extra: bigdb-mysql
Requires-Dist: pymysql>=1.1; extra == 'bigdb-mysql'
Provides-Extra: bigdb-postgres
Requires-Dist: psycopg2-binary>=2.9; extra == 'bigdb-postgres'
Provides-Extra: db
Requires-Dist: oracledb>=2.0; extra == 'db'
Requires-Dist: psycopg2-binary>=2.9; extra == 'db'
Requires-Dist: pymssql>=2.2; extra == 'db'
Requires-Dist: pymysql>=1.1; extra == 'db'
Provides-Extra: db-all
Requires-Dist: clickhouse-connect>=0.8; extra == 'db-all'
Requires-Dist: oracledb>=2.0; extra == 'db-all'
Requires-Dist: psycopg2-binary>=2.9; extra == 'db-all'
Requires-Dist: pymssql>=2.2; extra == 'db-all'
Requires-Dist: pymysql>=1.1; extra == 'db-all'
Provides-Extra: db-mssql
Requires-Dist: pymssql>=2.2; extra == 'db-mssql'
Provides-Extra: db-mysql
Requires-Dist: pymysql>=1.1; extra == 'db-mysql'
Provides-Extra: db-oracle
Requires-Dist: oracledb>=2.0; extra == 'db-oracle'
Provides-Extra: db-postgres
Requires-Dist: psycopg2-binary>=2.9; extra == 'db-postgres'
Provides-Extra: dev
Requires-Dist: build>=1.5.0; extra == 'dev'
Requires-Dist: eventlet>=0.37; extra == 'dev'
Requires-Dist: gevent>=24.11; extra == 'dev'
Requires-Dist: jsonschema>=4.26; extra == 'dev'
Requires-Dist: mypy>=2.3.0; extra == 'dev'
Requires-Dist: pytest-mock>=3.15.1; extra == 'dev'
Requires-Dist: pytest>=9.1.1; extra == 'dev'
Requires-Dist: ruff>=0.16.2; extra == 'dev'
Requires-Dist: twine>=7.0.0; extra == 'dev'
Requires-Dist: uvloop>=0.21; (sys_platform != 'win32') and extra == 'dev'
Provides-Extra: dingtalk-oa
Requires-Dist: mcp<3,>=2; extra == 'dingtalk-oa'
Provides-Extra: dingtalk-profile
Requires-Dist: keyring>=25.0; extra == 'dingtalk-profile'
Provides-Extra: docx
Requires-Dist: docling>=2.73.1; extra == 'docx'
Requires-Dist: markitdown[docx]>=0.1.7; extra == 'docx'
Provides-Extra: elasticsearch
Requires-Dist: elasticsearch<10,>=8.0; extra == 'elasticsearch'
Provides-Extra: email-all
Requires-Dist: google-api-python-client>=2.170; extra == 'email-all'
Requires-Dist: httpx>=0.28; extra == 'email-all'
Requires-Dist: msal>=1.31; extra == 'email-all'
Provides-Extra: email-gmail
Requires-Dist: google-api-python-client>=2.170; extra == 'email-gmail'
Provides-Extra: email-graph
Requires-Dist: httpx>=0.28; extra == 'email-graph'
Requires-Dist: msal>=1.31; extra == 'email-graph'
Provides-Extra: kafka
Requires-Dist: kafka-python>=2.0; extra == 'kafka'
Provides-Extra: media
Requires-Dist: docling-slim[format-video]<3,>=2.119.0; extra == 'media'
Requires-Dist: docling[asr]<3,>=2.119.0; extra == 'media'
Requires-Dist: setuptools<81,>=80; extra == 'media'
Provides-Extra: mongodb
Requires-Dist: pymongo>=4.6; extra == 'mongodb'
Provides-Extra: mysql
Requires-Dist: pymysql>=1.1; extra == 'mysql'
Provides-Extra: pdf
Requires-Dist: docling>=2.73.1; extra == 'pdf'
Requires-Dist: markitdown[pdf]>=0.1.7; extra == 'pdf'
Requires-Dist: onnxruntime<2,>=1.17; extra == 'pdf'
Requires-Dist: pypdfium2>=5.12.1; extra == 'pdf'
Requires-Dist: rapidocr>=3.9.2; extra == 'pdf'
Provides-Extra: postgresql
Requires-Dist: psycopg2-binary>=2.9; extra == 'postgresql'
Provides-Extra: ppt
Requires-Dist: docling>=2.73.1; extra == 'ppt'
Requires-Dist: markitdown[pptx]>=0.1.7; extra == 'ppt'
Provides-Extra: rabbitmq
Requires-Dist: kombu>=5.4; extra == 'rabbitmq'
Provides-Extra: redis
Requires-Dist: redis>=5.0; extra == 'redis'
Provides-Extra: service
Requires-Dist: alembic>=1.13; extra == 'service'
Requires-Dist: cryptography>=42.0; extra == 'service'
Requires-Dist: fastapi>=0.115; extra == 'service'
Requires-Dist: httpx>=0.27; extra == 'service'
Requires-Dist: minio>=7.2; extra == 'service'
Requires-Dist: python-multipart>=0.0.20; extra == 'service'
Requires-Dist: sqlalchemy>=2.0; extra == 'service'
Requires-Dist: uvicorn[standard]>=0.34; extra == 'service'
Provides-Extra: sql
Requires-Dist: sqlalchemy>=2.0; extra == 'sql'
Provides-Extra: tiktok
Requires-Dist: curl-cffi<0.17,>=0.14; extra == 'tiktok'
Provides-Extra: xlsx
Requires-Dist: docling>=2.73.1; extra == 'xlsx'
Requires-Dist: markitdown[xlsx]<0.2,>=0.1.7; extra == 'xlsx'
Requires-Dist: matplotlib>=3.11.1; extra == 'xlsx'
Requires-Dist: openpyxl>=3.1.5; extra == 'xlsx'
Description-Content-Type: text/markdown

# zleap_parser

`zleap_parser` 是 zleap 的**数据接入与归档 SDK**：把企业里散落在各处的数据——办公套件
（钉钉 / 飞书 / 企业微信）、代码仓库、邮件、数据库、RSS 与通用 API——通过**连接器**统一接入，
解析后归档为可迁移的知识型 `.octx` 文件，供下游 AI / RAG 直接消费。也支持把本地文件或远程
HTML 直接解析为 Markdown。SDK 以 pip 方式供下游项目导入；平台侧（`web/` + `service/`）在同一
套能力上提供私有化部署、多租户与用量治理。当前版本为 0.3.0，普通解析与连接器取数
不依赖外部事项提取或向量服务。

> 定位依据见 [plan/M3.3/positioning.md](./plan/M3.3/positioning.md)：对外主张是
> **数据接入与治理**，文档解析是其中一环（能力组件），不再作为对外卖点。

## 文档

1. [计划总览](./plan/PLAN.md)
2. [安装与快速上手](./docs/sdk/install.md)
3. [配置手册](./docs/sdk/configuration.md)
4. [文档解析 API](./docs/sdk/parse_api.md)
5. [连接器 API](./docs/sdk/connector_api.md)
6. [钉钉连接器与 MCP 方案](./docs/sdk/dingtalk_chat_mcp_pseudocode.md)
7. [服务 API 与部署](./docs/service/)

## Docker Compose 启动前后端

前端 Vue 控制台和 FastAPI 后端构建在同一个 `app` 镜像中，由 Nginx 提供前端并将
`/api/` 反向代理到后端。首次启动完整的本地环境（app + PostgreSQL + Redis +
MinIO）执行：

```bash
cp -n .env.example .env
./scripts/start_compose.sh start --bundled
```

脚本等待服务就绪，在容器内为 `.env` 中第一个 `AUTH_OPERATOR_EMAILS` 账号签发会话，
并直接打开 `http://localhost:8080/admin`。若 `.env` 已指向可用的外部 PostgreSQL、
Redis 和对象存储，只需启动应用：

```bash
./scripts/start_compose.sh start
```

已有容器需要重新进入后台时执行 `./scripts/start_compose.sh login`；停止完整环境使用
`./scripts/start_compose.sh stop --bundled`。数据保存在 Docker 命名卷中；完整配置与
零依赖 SQLite 启动方式见
[服务部署手册](./docs/service/deployment.md#6-compose-交付文件)。

`start` 与 `restart` 每次都会**自动增量构建** app 镜像——前端产物与 Python 代码都是
构建期 COPY 进镜像的，不重新构建就不会生效。服务镜像固定包含 PDF、Office、媒体、
连接器、缓存和全部数据库驱动，并固定使用 CPU 版 PyTorch（不携带 CUDA），不提供瘦身
构建入口；只想复用现有镜像时加
`--no-build`，只构建不动容器用 `./scripts/start_compose.sh build`。
扫描版 PDF 由 Docling 管线调用 CPU/ONNX RapidOCR 做全页中文识别。

## 安装

```bash
python -m pip install zleap_parser

# URL 采集首次使用时准备浏览器二进制
python -m camoufox fetch
```

可选能力通过 extras 安装：

```bash
python -m pip install "zleap_parser[pdf]"
python -m pip install "zleap_parser[xlsx]"
python -m pip install "zleap_parser[media]"       # 另需系统 ffmpeg
python -m pip install "zleap_parser[db-all]"
python -m pip install "zleap_parser[dingtalk-oa]" # 钉钉 OA MCP（可选）
python -m pip install "zleap_parser[dingtalk-profile]" # 钉钉加密 profile（可选）
```

SQLite、Markdown 归档和普通文本解析可直接运行。RTF/XLSX 预览需要系统
`soffice`/`libreoffice`；URL 采集需要 Camoufox 浏览器二进制。

## 最小示例

```python
import zleap_parser
from zleap_parser import CacheConfig, Parser

zleap_parser.config(cache=CacheConfig(cache_namespace="sdk-default"))
parser = Parser()

parsed = parser.parse(file="/path/to/document.pdf")
tree = parsed["result"]        # 默认 json：{root, files, tree} 目录树
print(tree["root"])            # 解包后的本地目录（knowledge/main.md + manifest.json + 附件）
print(parsed["usage"])         # 完整零用量账本

# 需要历史行为（返回 *.octx 路径）时显式指定：
octx_path = parser.parse(file="/path/to/document.pdf", output_type="octx")["result"]

csv_path = parser.pack_csv_to_octx("name,age\nAlice,30\n")
print(csv_path)
```

`Parser.parse(url=...)` 与 `Parser.parse(file=...)` 必须二选一。默认 `output_type="json"`：
归档仍会生成 `*.octx`，但返回值是解包后的文件目录树（`root`/`files`/`tree`），
调用方无需自行解包即可读取 `knowledge/main.md` 和附件。`output_type="octx"` 保持
0.2.x 的路径返回契约。归档产物包含 `knowledge/main.md`、metadata 和原始附件；不会生成
事项、关系或向量文件。

## 连接器

```python
from zleap_parser.connector import Connector, RSSAdapter

result = Connector().fetch(
    adapter=RSSAdapter(url="https://example.com/feed.xml", limit=20)
)
print(result["results"])       # 默认 json：目录树列表（每项 {root, files, tree}）
print(result["usage"])         # 普通数据源为完整零用量
```

`Connector.fetch(output_type="octx")` 返回历史行为的知识型 `*.octx` 路径列表。
内置数据源包括 RSS/WebSearch/DeepCrawl、企业微信/飞书/Salesmartly/钉钉
聊天与群列表、钉钉知识库/云盘/文档/OA 审批、邮件、API 请求、
GitHub/GitLab/Gitee/AtomGit 仓库、DB/BigDB、Twitter/X 个人主页、TikTok 作者主页视频、
Boss 直聘简历。所有数据源统一使用 `fetch()`；
邮件额外返回邮件 OCTX 列表和 sync-cursor OCTX。Git 仓库连接器的 `access_token` 可选
（公开仓库可省略）；GitLab 通过 `deployment` 区分官方 `https://gitlab.com` 与第三方/私有化地址。

`TwitterAdapter(profile_url="https://x.com/example")` 保存公开首屏帖子正文与照片，
每篇帖子独立归档为一个 OCTX，Markdown 正文只保留该篇文章内容，头部元数据通过 `source_url` 保存原帖 URL；
可注入逐篇触发的通用文档持久化钩子，MQ 投递暂留 TODO。
访问范围、资源上限和钩子用法见[连接器 API](./docs/sdk/connector_api.md#39-twitterx-个人主页)。

`TikTokAdapter(profile_url="https://www.tiktok.com/@example")` 按作者主页有限分页抓取公开视频，
每条视频独立归档为一个 OCTX，并强制下载视频文件作为该文档附件；连接器只处理匿名公开内容，
需要额外安装 `zleap_parser[tiktok]`。视频下载有 CDN 主机、SSRF、大小、超时和格式限制，
详情见[连接器 API](./docs/sdk/connector_api.md#310-tiktok-作者主页视频)。

Boss 直聘简历采集（`ZhipinResumeAdapter`，数据源名 `zhipin_resume`）需要先扫码
登录取得 Cookie，再按 JD 可选做 LLM 评分；采集结果输出 knowledge-only OCTX，
并额外写出结构化记录 `records.jsonl`，服务侧据此写入 `connector_resume`。
扫码登录与凭据落库方式见
[docs/service/zhipin_login_demo.md](docs/service/zhipin_login_demo.md)。

Git 仓库分析是唯一默认会调用模型的取数场景。它使用统一 `LLMConfig` 和
OpenAI-compatible 客户端，分析摘要写入 knowledge Markdown，代码文件作为
附件归档；usage 明细统一为 `kind="llm"`。

## 配置和多模态能力

文本及未来多模态请求统一使用 `LLMConfig`。`supports_multimodal=False` 为
默认值，只有显式设置为 `True` 才表示模型接受多模态消息；M2.8 不执行多模态
enrichment，不根据模型名猜测能力，也不静默降级。

`CacheConfig.cache_namespace` 默认 `"sdk-default"`，参与所有缓存 key/signature。
多租户服务必须为每个任务创建独立配置快照，例如
`tenant-<sha256(tenant_id) 前 32 位>`，不得在并发任务中修改全局配置。

## 文件格式

支持文本、源码、PDF、RTF、DOCX、PPTX、XLSX、HTML、XML、图片和音视频。
格式识别优先依据内容特征；新增格式通过 `BaseAdapter` 插件接入。

## API 变更

**0.3.0**

- `Parser.parse()` / `Connector.fetch()` 新增 `output_type`（`json` | `octx`，默认 `json`）：
  `json` 返回 materialize 后的文件目录树，`octx` 保持 0.2.x 的路径返回契约。
- 补齐连接器 SDK 导出：`ZhipinResumeAdapter` 等全部内置数据源均可从
  `zleap_parser.connector` 直接导入；新增回归测试锁定"注册即导出"。
- 历史上依赖 zleap-sag 的连接器提取入口已随该依赖彻底移除，不提供别名或兼容包装；
  当前只保留 `Connector.fetch()`。

**M2.8**

- 保留 `Parser.parse()`、`pack_to_octx()`、`pack_csv_to_octx()`、
  `pack_xlsx_to_octx()` 和 `Connector.fetch()`。
- 直接删除旧的事项提取/向量入口、旧连接器组合入口及其残留模块；
  不提供兼容别名、弃用警告或失败桩。
- 移除 embedding 配置和独立视觉模型/图片处理配置；只保留
  `LLMConfig.supports_multimodal` 能力字段。
- OCTX metadata 写入 `com.zleap.parser.archive_schema=knowledge-only/1`，
  capability 集合显式为空。

历史需求和旧版本行为请查阅 `plan/M1`、`plan/M2`、`plan/M2.5`、
`plan/M2.6`、`plan/M2.7` 及 `CHANGELOG.md`；这些记录不构成当前安装或 API 依据。
