Doclib SDK: DoclibClient
页码规范与历史结果兼容说明见 PDF 页码范围规范。
状态: Implemented
读者: SDK 开发者、mineru CLI 开发者、MCP/桌面端集成方
范围: 本地 doclib client 的公开能力、方法和错误模型
来源: 由旧 SDK 底稿迁移整理而来;旧底稿已归档删除
定位
DoclibClient 是本地 doclib 的 Product SDK。它通过 Unix Domain Socket 或 TCP loopback 连接 doclib server,使用本地文档库能力:
- 文件入库。
- 解析请求与缓存。
- 全文搜索和文件名搜索。
- 文件信息查询。
- watch、exclude、parsing rule 配置。
- server 状态和关闭。
它不是 v1 Unified API client。v1 API 面向 parse-server / mineru.net;doclib client 面向本机长期运行的文档库。
Doclib SDK 是 doclib 本地 API 的推荐承载方式。MinerU 项目内部除 doclib client 外,不直接通过 HTTP 协议访问 doclib API;外部客户端未来可以绕过 Python SDK,直接使用 doclib HTTP API 与 doclib server 交互。
当前实现类名是 DoclibClient,位于 mineru.doclib.client。是否额外提供 MineruClient 或顶层 mineru.client 别名仍是开放问题。
构造参数
当前构造签名:
from pathlib import Path
from mineru.doclib.client import DoclibClient
class DoclibClient:
def __init__(
self,
*,
endpoint_path: str | Path | None = None,
socket_path: str | Path | None = None,
base_url: str | None = None,
timeout: int = 60,
api_prefix: str = "/api/v1",
) -> None: ...
约束:
- 构造 client 不应启动 doclib server。
- 默认通过
$MINERU_HOME/doclib.endpoint.json发现 doclib endpoint。 - 默认发现不从启动配置推导 UDS 或 TCP;endpoint 文件不存在或无效时,方法调用抛出
ServerNotRunningError。 - 默认发现会在首次请求前校验 endpoint 与
/server/status的server_id;不匹配的 transport 不会承载业务请求。 - version 1 endpoint 仅用于升级迁移,通过 endpoint/status PID 对应关系识别旧 server;version 2 的 PID 不参与身份判断。
socket_path表示显式 UDS endpoint;base_url只表示显式 TCP endpoint,例如http://127.0.0.1:15980。- 显式
socket_path/base_url代表调用方明确选择的 server,不执行 endpointserver_id校验。 socket_path和base_url不能同时传入。- 无法连接任何候选 endpoint 时,方法调用抛出
ServerNotRunningError。 - client 提供
close(),调用方在 finally 中释放;当前不提供上下文管理器。
示例:
from mineru.doclib.client import DoclibClient
client = DoclibClient()
status = client.get_server_status()
Parse 方法
当前稳定入口使用 typed request / response model:
from mineru.doclib.types import ParseRequest, ParseResponse
def ensure_parse(self, request: ParseRequest) -> ParseResponse: ...
ParseRequest 语义:
| 参数 | 说明 |
|---|---|
path |
本地文件路径。 |
tier |
flash、basic、standard、advanced 或 None。None 表示使用 doclib 规则和默认策略;非 PDF/image 单文件未指定 tier 时归一为 flash,显式质量 tier 报错。 |
page_range |
页码范围。 |
force |
跳过已有 done 缓存并重新解析;可复用 active parse,只为未覆盖页创建新 parse。 |
remote |
是否允许调用远端 parse-server。默认 False。远端 URL 来自 doclib config;API Key 优先来自 doclib config,未配置时使用环境变量。 |
返回值是 typed ParseResponse:
class ParseResponse:
sha256: str
short_id: str | None
tier: str
page_range: str
status: Literal["pending", "done"]
cache_hit: bool
wait_parse_ids: list[int]
created_parse_ids: list[int]
reused_parse_ids: list[int]
tip: str | None
状态:
ParseResponse.status 只有 pending(已入队)和 done(已完成或命中缓存)两个取值。parse record(list_parses() / get_parse() 返回的 ParseInfo.status)使用更细的状态集合:
| 状态 | 含义 |
|---|---|
pending |
已入队,尚未开始解析。 |
parsing |
正在解析。 |
done |
解析完成。 |
failed |
解析失败。 |
superseded |
已被同文档同范围的新 parse 覆盖,默认不出现在 list_parses() 结果中。 |
当前没有稳定的 DoclibClient.parse(path, ...) convenience wrapper。CLI 会自行构造 ParseRequest,然后调用 ensure_parse(),再按需要调用内容读取接口。
Parse 与 Doc 辅助方法
| 方法 | 说明 |
|---|---|
list_parses(*, ids=None, doc_ref=None, tier=None, status=None, page_range=None, include_superseded=False, limit=50, offset=0) |
对应 GET /parses,按 ids、doc_ref、tier、status 或 page_range 查询 parse records 和覆盖状态;include_superseded 控制是否返回已被覆盖的 parse。 |
get_parse(parse_id) |
对应 GET /parses/{id},查询单条 parse record。 |
get_doc_content(doc_ref, *, tier, page_range=None, after=None, limit=30000, format="markdown", no_marker=False) |
对应 GET /docs/{doc_ref}/content,从保存的 JSON 结果读取时转换。 |
read_content(locator, *, after=None, context=0, limit=30000, format="markdown", image_format="jpeg", no_marker=False) |
对应 GET /content,按单点或页范围 locator 读取内容或图片。 |
export_doc_content(doc_ref, request) |
对应 POST /docs/{doc_ref}/exports,导出结构化内容。 |
invalidate(request) |
对应 POST /invalidate,将已有解析结果标记为失效;不自动触发重新解析。 |
parse_status(sha256, tier) 不再作为 NEXT 稳定方法;调用方应使用 list_parses(doc_ref=..., tier=...) 或 get_parse(parse_id)。get_doc_content() 是 doclib 层能力,不等同于 v1 Files API 的 GET /v1/files/{id}/content。
force=True 与 invalidate() 不等价。force=True 跳过 done cache,并通过 wait_parse_ids 等待复用或新建的 active parse;旧结果仍然有效。invalidate() 会让旧结果退出缓存命中、读取合并、搜索刷新和 compaction 选择。
Markdown 响应中的 visual block 图片使用 doc:.../page:.../block:... locator。非空图片 locator 可以原样传给 read_content(..., format="image");空 locator 表示该 block 没有可用图片。SDK 调用方不应依赖或拼接 Middle JSON 内部的 image_path。
请求定位器的 page: 复用输入页范围语法:数字、rN、1-5、r3-r1、1,3,r1、all。r1 表示最后一页,rN 和 all 需要文档总页数;返回定位器及块引用使用实际页码。带 block/char、图片读取和非零 context 都要求选中单页。
范围读取结束后 next_request=null。范围内截断时,同时返回规范化 locator 和实际页码 after;两者可直接传给下一次 read_content(),不会读入未选择的页面:
result = client.read_content("doc:ab12cd3/tier:flash/page:1,3", limit=1000)
if result.next_request is not None:
result = client.read_content(result.next_request.locator, after=result.next_request.after, limit=1000)
Search 与文件信息
def search(
self,
query: str,
*,
file_type: str | None = None,
tier: Tier | None = None,
min_tier: Tier | None = None,
limit: int = 20,
offset: int = 0,
) -> SearchResponse: ...
def find(self, query: str, *, ext: str | None = None, limit: int = 50, offset: int = 0) -> FindResponse: ...
def get_file_by_path(self, path: str) -> FileInfoResponse: ...
按路径查询文件信息使用 get_file_by_path(path),对应 GET /files/by-path;不存在独立的 info() 方法。
响应类型:
| 方法 | 响应 |
|---|---|
search() |
SearchResponse,包含全文结果、snippet、files、可空 tier;支持 file_type、tier、min_tier 过滤。 |
find() |
FindResponse,包含文件名前缀搜索结果;支持 ext 过滤及 limit/offset 分页。 |
get_file_by_path() |
FileInfoResponse,包含文件元信息、doc metadata 和 parse tiers。 |
search() 的 files 返回与文档 SHA 关联的全部 file aliases,按 file id 降序排列;每项包含 path、filename、ext 和 status。已索引的 orphan 文档使用空列表。active 优先只属于非 JSON CLI 展示策略,不改变 SDK 响应。解析内容的 tier 表示索引来源 tier;直接索引的 text 源内容为 null。传入 tier 或 min_tier 时,tier=null 的结果不参与匹配。
find() 默认仅对最后一个分词应用前缀匹配,显式尾部 * 等价。结果按相关性及 file id 排序,在扩展名过滤和文件状态刷新后计算 total 并分页。limit 必须为正整数,offset 必须为非负整数;偏移超过末尾时仍返回完整有效匹配数。HTTP GET /api/v1/find 接受同名参数,同步与异步接口保持一致。
Remote API 方法
| 方法 | 响应 |
|---|---|
get_remote_usage() |
RemoteUsageResponse,返回当前配置 Remote API 的 access level、billing period、current usage 和 limits。 |
该方法通过 doclib 读取 Remote URL 和有效 API Key,并调用本地 doclib route GET /api/v1/remote-usage。它不返回 Local Parse
Server 运行统计。
Config 方法
Doclib client 暴露运行时配置能力:
| 方法 | 说明 |
|---|---|
get_config() / get_config_key() |
返回运行时 KV 配置。 |
set_config() / unset_config() |
更新或删除运行时 KV 配置。 |
add_watch() / list_watches() / remove_watch() |
管理 watch target。 |
add_exclude_rule() / list_exclude_rules() / remove_exclude_rule() |
管理排除规则。 |
add_parsing_rule() / list_parsing_rules() / remove_parsing_rule() |
管理解析规则。 |
这些方法对应 配置体系 中的运行时配置,不负责启动前配置。
Server 方法
| 方法 | 说明 |
|---|---|
get_server_status() |
返回 doclib、队列、watch 和 parse-server 状态。 |
shutdown_server() |
请求 doclib server 关闭。 |
get_server_status() 是 CLI、MCP 和桌面端判断本地能力的主入口。
错误模型
doclib client 从服务端 error envelope 还原 MineruError:
| 场景 | 错误 |
|---|---|
| UDS / TCP 连接失败 | ServerNotRunningError。 |
| 服务端返回 error envelope | MineruError,保留 code、message、param。 |
| 服务端返回非 JSON | MineruError("internal_error", ...)。 |
SDK 不应把 doclib 内部异常原样泄漏给调用者。
隐私策略
ParseRequest.remote=False 是默认行为,表示不得上传到远端。此时 doclib 只能使用本地 flash 或 local parse-server。
只有调用方显式设置 ParseRequest.remote=True,doclib 才可以连接 remote parse-server 或 mineru.net。即便远端可用,SDK 也不能自动越过该开关。
接口扩展
当前入口为 DoclibClient,没有 MineruClient 别名、raw=True 或 parse(path, ...) 便利方法。
新增接口及异步客户端是否提供,统一在 当前待办 讨论,不作为当前 SDK 承诺。