qatlas 客户端 CLI 参考

当前内容契约更新:固定来源 PDF 已恢复为 paper_access 开关下的鉴权字节, 关闭404,qa_、别名、Range、历史原件不能绕过。新内容在独立 qatlas-content 桶的 content/ 命名空间不可变发布:source 绑定确切 PDF SHA,arXiv vN 是语义版本、 S3VersionId 是物理版本、parse revision 是独立不可变身份;三者不可混用。 同 paper/SHA 可复用 source;冻结导入别名不同字节409(overwrite也不替换)。 解析上传必须完整支持的 Middle+Markdown,保留所有成员原名/字节,MD-only拒收; manifest最后核验发布且PG必需,重传新revision,不覆盖历史。旧MD/JSON/images忽略, 只在内容/PDF访问按需冻结旧PDF,不bulk回填、不删除旧桶;没有nightly/boot/入库自动推理。 下文涉及旧三桶覆盖、仅full.md+images、原PDF410/外部直链的段落保留为历史背景, 不作为当前操作规则。当前API/上传/续读统一见论文内容契约 与Upload API;完整read视图不是原Middle JSON。

qatlas 是独立 PyPI 包 qatlas-cli 提供的 console script,由 IAI-USTC-Quantum/qatlas-cli 独立维护和发版。本文保留与 QuantumAtlas 服务端集成相关的命令参考;客户端源码、完整命令和版本更新以该仓库及 qatlas --help 为准。

旧包 quantum-atlas 退役

quantum-atlas 0.21.0 是仅含元数据的最终迁移版,不含 qatlas 模块、parser 库或 console entry,没有运行时依赖,也不会自动安装 qatlas-cli。安装 QuantumAtlas 主仓同样不会提供 qatlas。旧用户请按迁移步骤先卸载旧包,再用原安装器安装 qatlas-cli;不要删除 ~/.config/qatlas。

顶层

qatlas [--version] [--help] <subcommand> [args...]

顶层选项

含义

--version / -V

打印 qatlas X.Y.Z

--help / -h

列出所有子命令 + 别名

通用 client flag

所有调 server 的子命令(paper / contrib 等)都接受这个 flag:

Flag

默认

含义

--request-timeout <seconds>

120.0

单 HTTP 请求超时(per-call 临时调)

v0.17.0 删除了 --base-url / --token / --insecure flag

服务器 URL / token / TLS 选项现在只能写在 ~/.config/qatlas/config.yaml。短命令调用是 client 的主要使用场景,每次重新指 server 反而麻烦。如果有"两个项目走两个 server"的需要,用 XDG_CONFIG_HOME=/path/to/other-config qatlas ... 临时切(freedesktop 标准机制)。


客户端命令

qatlas config

inspect / edit user-level YAML 配置文件(路径按平台,见下方表)。首次跑任何 qatlas <cmd> 自动创建模板——不再需要 qatlas config init 步骤。给 uv tool install 用户用,不需要 export 任何 env。

跨平台配置文件路径(由 platformdirs 解析,跟主流 Python CLI 一致):

平台

默认路径

控制 env

Linux

~/.config/qatlas/config.yaml

XDG_CONFIG_HOME

macOS

~/Library/Application Support/qatlas/config.yaml

—

Windows

%APPDATA%\qatlas\config.yaml

APPDATA

不确定具体到哪 → qatlas config path 打给你。本文档后面的例子用 Linux 形式 ~/.config/qatlas/config.yaml,mac / win 用户照着替换路径即可。

qatlas config <subcommand>

Subcommand

含义

path

打印 yaml 文件路径(无论是否存在)

set <key> <value>

写一个 key=value。key 用 snake_case YAML 字段名(如 server_url / token / mineru_api_tokens),不再用 env-var 大写形式。文件不存在时自动建(0600 perms)。敏感字段(含 token / secret / key / password)echo 时遮罩

unset <key>

删除一个 key

get <key>

打印 key 在 yaml + Field default overlay 后的真值。无值时 exit 1,适合 shell 插值

show [--unmask]

dump 所有字段(snake_case key: value 形式);敏感值遮罩,--unmask 完整打印

配置入口(v0.17.0+ 极简):

  1. 平台原生配置文件路径(见上表)— 唯一配置源(首次跑任意命令自动创建)

  2. 内置 Field default — 由独立 qatlas-cli 仓库中的客户端配置模型定义,不在 QuantumAtlas 主仓中

没有 CLI flag overrides,没有 OS env vars,没有 $QATLAS_DOTENV / $QATLAS_CONFIG。这是有意的极简化——client 用户基本是"配一次长期用"的模式,多入口反而增加心智负担(v0.16 起 client 不再借 server 的 .env 跑)。

想换 config 文件位置?用平台标准 env

  • Linux: XDG_CONFIG_HOME=/etc/myconfig qatlas <cmd> → yaml 落 /etc/myconfig/qatlas/config.yaml

  • macOS: 没有 platformdirs 支持的标准 env,唯一办法是 symlink ~/Library/Application Support/qatlas/

  • Windows: APPDATA=D:\my-config qatlas <cmd> → yaml 落 D:\my-config\qatlas\config.yaml

都是 freedesktop / Microsoft / Apple 各自平台的原生机制(platformdirs 透传),不是 qatlas 自己定义的 override。

qatlas config set 会抹掉手写注释

PyYAML 不保留 round-trip 注释,跟 gh / kubectl config set 行为一致。要永久注释,直接编辑 yaml 不用 set。auto-init 写出的 header 注释每次 set 都会被重写,是预期行为。

典型 workflow:

# 首次安装 + 配置(v0.17.0+)
uv tool install qatlas-cli
qatlas --help                                       # 任意命令都触发 yaml 自动创建
qatlas config set server_url https://quantum-atlas.ai
qatlas auth login -s quantum-atlas.ai               # OAuth device-code flow → 自动写 hosts.yml
echo '[jwt-a, jwt-b]' | qatlas config set mineru_api_tokens  # 若要跑 qatlas contrib mineru(CSV / 列表均可;sensitive key 从 stdin 读)

# 看 yaml 路径
qatlas config path
# /home/you/.config/qatlas/config.yaml

# 看效果
qatlas config show
# server_url: https://quantum-atlas.ai
# (token 不在 config.yaml;通过 `qatlas auth status` 查 hosts.yml)
# ...

# 之后任何 qatlas 子命令直接跑
qatlas paper get markdown 2501.00010v1 -o paper.md
qatlas contrib mineru --batch-size 3

v0.16 / 更早升级到 v0.17.0:删了 qatlas config init 子命令、删了 .env → yaml 自动迁移。如果你之前在用 ~/.config/qatlas/.env,手工把内容搬到 ~/.config/qatlas/config.yaml(字段名从 QATLAS_SERVER_URL 改成 server_url、MINERU_API_TOKEN 改成 mineru_api_tokens(列表形式),去掉 QATLAS_ 前缀小写化),原 .env 删掉。

详细:管理凭证、入门。


qatlas ingest(已移除)

ingest 子命令及其服务端端点(POST /api/ingest/paper 等)已随客户端 重构移除。原「让 server 抓论文并解析」的能力拆到了现役命令:

原用法

现用法

qatlas ingest <arxiv_id>

qatlas paper get markdown <arxiv_id>(缓存未命中自动触发服务端抓取 + MinerU 转换,LRO 轮询)

qatlas ingest status <task_id>

qatlas paper status <arxiv_id>

--force-fetch / --force-parse

贡献者走 qatlas contrib pdf --overwrite / qatlas contrib mineru


qatlas contrib

贡献者日常入口(v0.19.0 起的正式命令面)。把"上传 PDF"和"本地跑 MinerU 再推回"两件事归到一个名词下:

qatlas contrib pdf <arxiv_id> --pdf <path> [--overwrite]
qatlas contrib mineru [<arxiv_id>] [--watch] [...]

qatlas contrib pdf

上传本地 PDF。需要 papers:write scope。

qatlas contrib pdf <arxiv_id> --pdf <path> [--overwrite]

Flag

必填

默认

含义

<arxiv_id>

✅

—

必含版本 vN,如 2501.00010v1

--pdf <path>

✅

—

本地 PDF 文件

--overwrite

❌

false

字节不同时允许覆盖(旧版本保留在 S3 versioning 中)

调用:POST /api/papers/{arxiv_id}/upload-pdf(multipart),自动加 ?expected_sha256=<hex>。

详细 how-to:贡献内容,详细 API:Upload API。

qatlas contrib mineru

本地用自己的 MINERU_API_TOKENS 跑 MinerU 解析,把结果(markdown + images)推回 server。三种模式:

qatlas contrib mineru                               # 队列模式:申请 lease 并处理 server 的 needs-mineru 队列
qatlas contrib mineru <arxiv_id>                    # 单篇模式
qatlas contrib mineru --watch [--watch-interval N]  # 守护循环

Flag

默认

含义

<arxiv_id>

—

省略 = 队列模式遍历 server 的未处理列表;给定(必含版本)= 只处理这一篇

--batch-size N

MinerU 单批上限

队列模式每批最多几篇

--continue-on-error

off

队列模式遇到单篇失败继续(批模式下隐式开启)

--ttl-seconds N

server 默认 1800(max 7200)

MinerU lease 租约时长

--no-cache

off

让 MinerU 绕过 server 端缓存

--overwrite

off

覆盖 server 上已有 markdown / images

--no-push

off

跑 MinerU 但不上传,结果 zip 留在临时目录、立即释放 lease

--watch

off

守护模式:每轮排空队列后 sleep --watch-interval 再轮询;隐含 --continue-on-error,SIGINT/SIGTERM 处理完当前篇干净退出

--watch-interval N

300

守护模式两批之间的轮询间隔(秒)

需要 papers:write scope。详细 how-to:贡献内容 / 用 MinerU 解析。


qatlas paper

读 server 端缓存的 Markdown 字节与论文元数据。需要 papers:read scope。 资产读取(markdown / images)仅对开启 QATLAS_PAPER_ACCESS_ENABLED=true 的 self-hosted 实例可用——公开 quantum-atlas.ai 默认关,调用会被路由 404;get metadata 走论文详情端点 (GET /api/papers/{id}),不受该开关限制。

qatlas paper get markdown ID_OR_DOI [--output FILE | --no-wait]
qatlas paper get images   ID_OR_DOI [--output FILE]   # MinerU 图片 zip(显式获取)
qatlas paper get metadata ID_OR_DOI                   # 论文详情 JSON(JSON-only、无 abstract,机器可读出口)
qatlas paper status       ID_OR_DOI [--kind markdown]

# 当前固定原PDF用 qatlas paper pdf;可续读派生JSON用 qatlas paper read

ID 形态(server 自动归一)

输入

server 推断

完整 0811.3171v3 / quant-ph/9508027v2

不动

无版本 0811.3171 / quant-ph/9508027

自动加 latest vN(优先查本地 catalog,未收录才 fetch /abs/<id> HTML og:url)

bare old-style 9508027 / 9508027v2

自动加 category=quant-ph(生产 bootstrap 假设;详见 arxiv-ids §3.1)

DOI 10.1103/PhysRevLett.103.150502

OpenAlex 反查 → arxiv id

qa_ paper_id(qa_01H…)

解析成该论文的 canonical 身份:最高已收录 arXiv 版本(DOI-only 论文走 DOI 管线)

每应用一次默认值,CLI 在 stderr 打一行 Note (server applied defaults): ..., 来自 X-QAtlas-Defaults-Applied 响应头。--quiet-notes 抑制。

长任务(LRO)行为

cache miss 时 server 返 202 + Operation-Location 启动后台 silent fetch / MinerU convert。CLI 自动 poll /{markdown|pdf}/status,每轮打一行紧凑 进度到 stderr:

... waiting: queued converting_md fetch=4503234B convert.running polls=7 queue=#3(2ahead,4/4slot) eta=240s

--quiet-progress 抑制;--no-wait 完全跳过 poll 直接吐 202 JSON 退出 0 (适合脚本异步编排)。

错误展示

任何 4xx / 5xx 或 body-level 终态(state=failed / cooldown / unavailable), CLI 把 server JSON body 整段 pretty-print 到 stderr——包括 detail / kind (fatal | retryable | daily_limit)/ phase / retry_after_iso / arxiv_id | doi | canonical / 以及 echoed requested_id / resolved_id / defaults_applied。这样 agent 一次就拿到判断要不要重试、什么时候重试、原始 ID 解析到了哪一步所有信息。

Flag

Flag

子命令

默认

含义

<id_or_doi>

全部

必填

arxiv id、DOI 或 qa_ paper_id(见上表)

--output / -o FILE

get

stdout

字节写到 FILE;- 或省略 = stdout

--no-wait

get

false

cache miss 时不 poll,直接吐 202 JSON 退出 0

--max-wait N

get

1800

poll 总时长上限(秒);超时退出 1

--quiet-progress

get

false

不打 ... waiting 行

--quiet-notes

get / status

false

不打 Note (server applied defaults) 行

--kind markdown|pdf

status

markdown

状态端点的两种

退出码

码

含义

0

字节成功 stream 完 / --no-wait 收到 202 / status 拿到 JSON

1

terminal failure(404 / 5xx / state=failed / cooldown / 超时)

2

flag 解析错误

调用链

  • get 命中缓存:GET /api/papers/{id_or_doi}/{kind} → 200 + 字节

  • get 未命中:同上 → 202 → 周期 GET .../status → cached → 重发 GET .../{kind} → 200 + 字节

  • status:单次 GET .../{kind}/status

详细 LRO 协议、Phase 字段语义、agent 决策三元组见 冻结内容访问 · 异步读取。


qatlas contrib mineru

本地跑 MinerU 解析 server 上的 PDF,推回完整 MinerU bundle。需要 papers:write scope + 本地 mineru_api_tokens 至少一条。

qatlas contrib mineru [arxiv_id] [options...]

Flag

必填

默认

含义

<arxiv_id> (可选)

❌

—

指定单篇;省略走队列模式

--batch-size N

❌

50

队列模式:每批最多多少篇(硬上限 50 = MinerU 单批限制)

--max N

❌

—

已弃用,--batch-size 的兼容别名;两个都给时 --batch-size 优先

--continue-on-error

❌

false

队列模式:单篇失败继续下一篇(batch 模式下隐式启用)

--ttl-seconds N

❌

server 默认 1800

MinerU lease 租约(最长 7200)

--no-cache

❌

false

让 MinerU bypass 服务端缓存

--overwrite

❌

false

server 已有 markdown 时仍允许覆盖

--no-push

❌

false

跑 MinerU 但不推回(留 tmp zip)

--watch

❌

false

daemon 模式:跑完一批 sleep --watch-interval 再继续(Ctrl-C 干净退出;daily-limit 命中自动 sleep 到次日 00:01)

--watch-interval N

❌

300

daemon 模式 sleep 秒数(不影响 daily-limit 命中后的睡眠时长)

退出码:成功 = 0;失败 = 1;MinerU 每日额度耗尽 = 75(EX_TEMPFAIL,CI 可视为 transient 重试)。

调用链(单篇模式):POST /api/v1/papers/{id}/mineru-lease → MinerU 单 task → POST /api/papers/{id}/upload-mineru → DELETE /api/v1/papers/{id}/mineru-lease/{cid}。

调用链(队列 / daemon 模式,v0.15.0+):list needs-mineru → 逐篇申请 MinerU lease → 一次 POST /api/v4/extract/task/batch → 周期 GET /api/v4/extract-results/batch/{id} → 每 done 立即 upload-mineru + 释放 lease。

详细:用 MinerU 解析。


qatlas auth

管理本地存储的 PAT。

qatlas auth login [-s | --server-url <URL>]
                  [--no-browser]
                  [--scopes a,b,c]
                  [--expires-days N]
                  [--token-name NAME]
                  [--timeout SEC] [--insecure]
                  [--with-token]
qatlas auth logout [-s | --server-url <URL>]
qatlas auth status [-s | --server-url <URL>]
qatlas auth token  [-s | --server-url <URL>]

子命令

行为

login

走 RFC 8628 device-code 流程:POST /api/oauth/device/code 拿 user_code + verification 深链 → 自动开浏览器(除非 --no-browser) → 用户在 /<lang>/device 表单里编辑 name/scopes/expiry 然后 Approve → CLI 轮询 /api/oauth/device/token 拿到 PAT 明文写 hosts.yml。--with-token 是 CI 旁路

logout

删该 host 的本地条目(不调 server)

status

列已登录的 host + 脱敏 token 预览

token

把指定 host 的明文 token 打到 stdout(shell 替换:curl -H "Authorization: Bearer $(qatlas auth token)")

Flag

默认

含义

-s / --server-url

server_url: from config.yaml, else interactive prompt

操作哪个 server;接受裸 hostname (quantum-atlas.ai) 或完整 URL (https://quantum-atlas.ai:4200),自动 normalize 成 hosts.yml key

--no-browser

off

不调 webbrowser.open —— 只打印 URL,自己复制到任意有浏览器的设备打开

--scopes a,b

空

预填到浏览器表单的 scope;空 = 浏览器默认全勾(用户可改)

--expires-days N

90

预填到表单的过期天数 (1–365);浏览器可改

--token-name NAME

qatlas-cli-<host>-<YYYY-MM-DD>

预填到表单的 token 名;浏览器可改

--timeout SEC

600

CLI 等浏览器 approve 的秒数

--insecure

off

信任自签证书(IP 入口 / 用 tls internal 的边缘节点)

--with-token

off

CI 旁路:从 stdin 读 PAT(cat token | qatlas auth login -s ... --with-token),跳过 OAuth 直接存进 hosts.yml;secret 不进 argv / shell history。跟 gh auth login --with-token 同款设计——故意不暴露 argv 形式

注意:所有非 CI 旁路的 flag 都只是预填,最终 token 的 name / scopes / expiry 以浏览器里点 Approve 时表单上的值为准——这设计就是为了让用户不必每次都精确记得自己想要哪几条 scope,先 qatlas auth login 跑起来再在浏览器里挑。

v0.19.0 删了 qatlas config set token 路径——config.yaml 的 token: 字段会静默盖 hosts.yml 里所有 per-host token,是 footgun。所有 PAT 现在都通过 qatlas auth login(OAuth)或 qatlas auth login --with-token(CI stdin)走 hosts.yml。

文件 layout 是 YAML,0600 权限,详见 管理凭据。


插件命令(独立仓库提供)

qatlas 的部分顶层命令由独立插件包提供(entry-point 组 qatlas.plugins 发现,安装插件包后命令自动出现,未安装时 CLI 会给出安装提示):

命令

插件包

说明

qatlas search

qatlas-search

多源论文搜索(agentic 微服务,含本地语义检索 backend)

qatlas rag

qatlas-rag

直接查询 qatlas-rag 语义检索服务(POST /v1/retrieve),支持 --server / --token / --max-results / --json

qatlas match

qatlas-match

论文身份高精度匹配:判定 qatlas-id / DOI / arXiv / OpenAlex / URL / 标题是否已入库并返回统一 qa_… id(标题必须每个单词都匹配;--author / --year 消歧,--json、部署机 --direct)

三个插件仓库均为私有仓(IAI-USTC-Quantum/qatlas-search、 IAI-USTC-Quantum/qatlas-rag、IAI-USTC-Quantum/qatlas-match),按提示中的 uv tool install --from git+ssh://... 方式安装。qatlas rag 需要能访问 qatlas-rag 服务(默认 127.0.0.1:8801,即部署该服务的主机或可达的内网 地址);qatlas match 默认经 qatlasd 的 POST /api/papers/match 代理调用 (需 papers:read scope 的 PAT),--direct 仅面向部署机就地连库。

已退役的旧 Python 入口

QuantumAtlas 主仓不再分发原 qatlas/ Python helpers,也不再提供旧 monolith 的 qatlas parser / parse 入口。quantum-atlas 0.21.0 不包含这些代码;不要通过安装主仓或旧包恢复它们。客户端可用命令以独立 qatlas-cli 的 qatlas --help 为准。


环境变量影响

v0.17.0+:client 端不读任何 OS env。所有 client 配置必须经 ~/.config/qatlas/config.yaml 或 ~/.config/qatlas/hosts.yml 持久化。

变量

谁读

作用

XDG_CONFIG_HOME

所有 qatlas 命令

config.yaml + hosts.yml 父目录(默认 ~/.config)

XDG_DATA_HOME

服务端 qatlasd

默认 raw/data/pb_data 父目录

QATLAS_* env

server 端 qatlasd,参见 qatlasd CLI + env vars

client 不读

完整列表:环境变量参考。