论文内容:固定 PDF、完整解析包与可续读视图¶
本文是当前内容 API 的契约。旧三桶路径、覆盖写、GET /pdf 恒 410、只接收
full.md + images 的说明只作为历史记录保留,不适用于本契约。
身份与存储边界¶
paper_id=qa_…标识作品,不表示某个 arXiv 版本或某次解析。source_id绑定确切 PDF 字节及完整 SHA-256。同一 paper 下同 SHA 的新登记 复用已有 source ID;既有评论及其 source 不换号。arXivvN是上游语义版本,origin可以是arxiv:vN/arxiv:IDvN,不是对象存储的S3VersionId。 两个语义版本字节相同可以共享 source;不同字节不能冒充相同冻结来源。revision_id标识一次不可变完整解析发布。重解析或重上传产生新 revision;is_current是可变选择指针,不能改写旧 revision 或迁移历史评论锚点。S3VersionId是存储后端的物理对象版本,只供运维诊断/恢复,不是 source ID、 arXivvN、parse revision 或公开 API 的版本选择参数。S3 versioning 不能代替 上述应用级不可变身份,也不允许通过恢复覆盖已冻结的 API 内容。
新字节放在独立内容桶 qatlas-content(本地部署使用相同逻辑命名空间),逻辑键:
content/{paper_id}/{source_id}/source.pdf
content/{paper_id}/{source_id}/parses/{revision_id}/files/{producer_original_relative_path}
content/{paper_id}/{source_id}/parses/{revision_id}/manifest.json
文件成员保留生产者的相对路径、原文件名与原字节,包括 Middle、Markdown、
Structured Content/ContentList、图片和未知合法成员。服务端不把 layout.json
改名为 middle.json,不把任意 JSON 改名为 content_list.json,不重序列化原件。
生成的 manifest.json 独立于 files/,不会占用或覆盖生产者同名文件。
成员逐个 create-only 写入并从持久存储复核 SHA/大小;所有成员核验后才写 manifest, 最后才在 PostgreSQL 发布完整 revision 并切换 current。PG 不可用时上传失败, 不能返回“已成功,索引稍后补登记”。只完成对象写入但未发布的内容不是 ready。
开关、认证与懒迁移¶
所有 PDF、正文、raw JSON、完整包成员、block 原件/裁图、图片与 figures 都受
paper_access.enabled 和当前登录身份的 papers:read 约束;关闭返回 404,不能
以 qa_、别名、Range、历史 revision 或客户端缓存绕过。目录元数据及评论信息
不因此变成原件交付入口。配置字段及部署方法见服务端配置。
数据库迁移只增加表、指针及约束,不批量下载、转换或回填历史资产。
首次内容/PDF访问按需读取旧库的PDF,计算 SHA 并冻结到新内容命名空间; 旧 MD、JSON、图片不复制、不作为新 ready 的证据。旧桶/旧文件保持原样不删除。
已有冻结来源缺失、摘要错误或存储不可达时 fail closed,不能回退旧 PDF、恢复 另一物理版本、替换为最新 arXiv PDF或重新解析来掩盖问题。
已存 PDF 的读取不需要 MinerU token,也不做推理。只有显式正文/内容访问可触发按所选 source 的懒解析;状态轮询不创建下载/解析任务。没有 nightly、boot、入库或下载归档 自动推理,也不做 bulk 懒迁移;管理员明确调用 RunNow/batch 仍是受控的独立操作。
历史
/parses/{revision}/json继续服务明确固定的评论原件,不参与新完整包 readiness 判断。新读视图及完整成员 API 仅接受已发布且核验的完整包。
固定来源 PDF¶
GET /api/papers/{id}/pdf?source_id=SOURCE_ID
GET /api/papers/{id}/pdf?version=v2
GET /api/papers/{id}/sources/{source_id}/pdf
id 可为 qa_、arXiv 或 DOI 等可解析别名。source_id 与 version 互斥;显式
pin 无匹配或存在歧义时拒绝,不换成另一个 source、最新版或出版版。无需先调用
source-list,旧 PDF 也可按需冻结后直接读取。默认成功为鉴权 application/pdf
字节流(200;合法 Range 为 206,使用相同认证),不是外部预签名链接,也不是 410。
?format=link 只返回同源、固定 source 的 /api/papers/{qa}/pdf?source_id=S&format=bytes
认证下载位置,不暴露桶地址或外部 presign;每次跟随链接仍检查 gate/auth。
响应通过 X-QAtlas-Paper-Id / X-QAtlas-Resolved-Id、X-QAtlas-Source-Id、
X-QAtlas-Source-Origin、X-QAtlas-Sha256 / X-QAtlas-PDF-SHA256 给出身份与摘要。
完整文件可按 SHA 校验;部分 Range 不是完整 PDF 摘要的校验单位。
qatlas paper pdf qa_… --source-id src_… -o paper.pdf
qatlas paper pdf 0811.3171v2 --version v2 --no-cache -o paper-v2.pdf
CLI 对规范 ID 和别名均逐块计算 SHA,校验通过才输出。缓存按服务+规范 paper+SHA 寻址;每次命中缓存前仍取得当前服务端鉴权/开关许可响应,禁用或 401/403 不会 伪装为缓存成功,且不会删除此前已合法下载的文件。
Middle 派生 JSON 阅读窗口¶
GET /api/papers/{id}/read?source_id=S&revision=R&page=5&block=12&limit=30000
GET /api/papers/{id}/read?cursor=OPAQUE_CURSOR
参数均可省略:source_id 固定 PDF;revision 固定解析;page/block 为 1-based
页码和生产者原始 block index(非连续索引不重编号),block 必须带 page;cursor
是服务端返回的不可改写游标;limit 是 Unicode 正文字符预算,默认 30000,范围
1..100000。HTTP 亦支持共享来源解析器的 version=vN 语义 pin,与 source_id 互斥。
200 JSON 保留:
字符串
paper_id、source_id、revision、source_sha256、artifact_sha256、 可选bundle_sha256、renderer、format=markdown、content;request_scope(选择 page/block、limit、可选 cursor);content_ranges[](page/block、start_offset/end_offset、start/end locators);truncated布尔值、可空next_request、可选warnings[]。
原生 mineru.native.middle/pdf_info-v1 使用独立 renderer
qatlas-mineru-native-markdown-v1,不改变已发布 DocVortex 的 renderer/游标文本。
只构建内存消费视图:公开 page=page_idx+1、block=native index+1(原生编号0-based);
保留编号空隙,不用数组位置补造锚点,子块不冒充新的顶层锚点。原始 index/JSON位置仍
可在固定 layout.json 对照。原生页单位 bbox 按有效 page_size 转为 [0,1] 供裁图,
非法/缺失 bbox 不钳制、不虚构,返回警告或不可裁图;不把转换结果写回原件。
content_ranges 的 start_offset/end_offset 为渲染 Markdown 的 Unicode rune 半开区间,
不是原 JSON 字节位移;窗口可切进 Markdown 语法,按原样拼接连续 content 才恢复选定文本。
这是由 Middle 生成的阅读信封,不是 Middle 原 JSON,不是 Structured Content,
更不是“截断后的原始 artifact”。若 truncated=true,将 next_request.cursor
原样传回下次请求。游标固定 paper/source/revision、PDF与Middle/完整包摘要、renderer
及选择范围;cursor-only 先解析这些 pins,再决定加载哪一 revision,不能先选
当前最新版。显式 pin/选择冲突或 renderer/摘要身份变化返回 409;格式错误返回 400。
qatlas paper read qa_… --source-id src_… --revision REVISION --page 5 --block 12 --json
qatlas paper read qa_… --limit 30000 -o first-window.json
qatlas paper read qa_… --cursor 'next_request.cursor 的原字符串' --json
未固定 revision/cursor、所选来源的完整包尚未就绪时,仅显式内容 GET 可启动该
exact source 的解析(source_id仅固定PDF,不固定解析修订),响应 202 和 Retry-After: 5。
明确 revision/cursor 的缺件或坏摘要不能创建替代解析;明确 source 的PDF缺失也不另抓其他版本。
已知来源时 Operation-Location: /api/papers/{canonical}/read/status?source_id=S;
来源尚未知的合法 fresh DOI/明确 arXiv请求保留原请求身份的 read/status 位置,按内容意图
抓取→冻结→解析,来源建立后才给source pin。PDF GET仅抓取/冻结,不启动推理。
GET /api/papers/{id}/read/status?source_id=S&revision=R
status 是纯轮询:不调用 EnsureSource、不创建任务。响应带顶层
paper_id、source_id、source_sha256、revision、state、ready。
完整来源/manifest/成员校验成功才 state=cached、ready=true(200),兼容 md_ready/pdf_ready
及 source/revision固定的 read_url/markdown_url;pending/queued/running 可返回 202
和同一 Operation-Location/Retry-After;failed/none 或 HTTP 错误不等于就绪。
bundle_sha256 是完整 manifest 的摘要(逻辑包指纹),不是原 ZIP 压缩字节摘要。
客户端也兼容 ready/cached/done 状态:就绪后携固定 source/revision 重取原 read 请求。
进程 Done 或历史 Middle 存在不足以判定新内容 ready。
--no-wait 返回初始 JSON(包含轮询位置/重试间隔);默认 CLI 有界轮询,超时或
failed/cooldown/unavailable 报错,stdout 不混入进度文字。同源校验防止把 PAT 发到
Operation-Location 指向的外站。
原始产物与清单¶
GET /api/papers/{id}/parses/{revision}/manifest
GET /api/papers/{id}/parses/{revision}/files/{original_relative_member_path}
GET /api/papers/{id}/parses/{revision}/json
manifest 是单独生成的清单,字段为 version=1、paper_id、source_id、
revision_id、source_pdf_sha256、middle_path、markdown_path、
files[{path,size_bytes,sha256}]。按清单中原始 path 请求成员,嵌套目录不扁平化;
所有原始 JSON 与图片等均可获取。未知/不可信类型按 attachment + nosniff 交付,
允许的栅格图片可 inline。路径穿越、未知成员拒绝,成功成员仍逐个复核完整 SHA。
/json 仍为该 revision 的字节完全一致的 Middle artifact;固定历史评论
使用它,不取“最新解析”替换。CLI paper parse-json ID REVISION 继续输出校验后的
原字节,和 paper read 的派生视图不是同一产物。
上传与解析协议¶
fresh PDF/解析上传写新内容桶。成功绑定的导入别名(如明确
arxiv:IDvN)永久 指向首次成功的确切 PDF;同别名不同字节返回 409,即使 overwrite=true。 新语义 arXiv vN 或独立新 source 是新身份,不通过覆盖旧 source 实现。upload-mineru要求完整受支持 Middle 及markdown.md/full.md: 保留docvortex.middle/schema_version 2.0,也支持实际 hosted V1 standard/hybrid 的 原生layout.json(pdf_info数组),记录为mineru.native.middle/pdf_info-v1。 原生文件没有 DocVortex schema 标识,不向原件添加或伪造这些字段;原名/字节不变。 MD-only、ContentList-only、缺件及无效 schema 拒收;图片可为空。ZIP 所有合法原名/字节保留,未知成员也不丢。路径穿越、绝对/反斜杠路径、 重名、symlink、CRC错误等导致整包失败。当前限制 ZIP 128MiB、单成员128MiB、 解压合计256MiB、文件数10000。原 ZIP 可额外留存,但不替代完整成员/manifest。
重上传是新 revision;overwrite 参数不会修改既有 revision。只有完整、校验 成功且 PG 已发布的包才可 current。详见Upload API。
服务端 MinerU hosted V1 在
/api/v1命名空间走 uploads/create → PUT → complete/file.id → parse/jobs(要求 output_formats:[zip]), tier 默认standard(flash/basic/standard/advanced),ocr_mode 为 auto/ocr。 legacy V4 的 model_version、language、formula/table 字段是另一协议,不能当成 V1 tier/OCR 参数;metadata 中 tier 标签也不代表服务器已执行相应质量档位。gate开启时 claim的PDF URL也是同源认证locator(pdf_requires_auth=true),不是S3 presign;不可向第三方解析器转发PAT。须先鉴权获取exactPDF再按provider协议上传。 gate关闭时仅给外部arXiv URL及目录SHA。PDF/search/list不触发推理或RAG正文读取, RAG索引发布只跟随显式解析完成。
错误与升级注意事项¶
关闭开关/缺少指定原件为404,认证失败401,scope不足403,输入错误400,身份或游标 冲突409,完整包/冻结字节完整性失败422,后端不可用503。显式 pin 失败不自动修复、 替换或回退。客户端须与服务端 major.minor 对齐;本契约涉及兼容性变化,按协调的 下一 minor RC 发布,未发布前不要把旧客户端/旧服务行为当成已升级。
旧桶与物理版本继续保留供运维,禁止为本功能做无授权批量迁移、删除或覆盖。 历史布局/ADR只记录当时设计,当前操作遵循本页与实际版本 OpenAPI。