mcpField
L
Lium GPU Cloud

Lium GPU Cloud

本地服务
lium.io云与基础设施7今天更新

关于 Lium GPU Cloud

Lium 提供命令行工具和 Python SDK,用于在 Lium 平台租用及管理 GPU pod。它支持单 pod 任务和多节点集群,可执行命令、运行后台任务并移除资源。

主要功能

  1. 01租用和移除 GPU pod
  2. 02执行命令并查看 GPU 状态
  3. 03将 Python 函数交由 pod 运行
  4. 04运行后台任务并重新连接
  5. 05创建多节点集群

适用场景

  1. 01运行 GPU 推理或训练
  2. 02通过脚本自动管理 pod 生命周期
  3. 03在多个 GPU 节点上运行分布式任务

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"datura-ai-lium": {
"command": "uvx",
"args": [
"lium.io"
],
"env": {
"LIUM_API_KEY": "<LIUM_API_KEY>"
}
}
}
}
启动命令uvx lium.io
需要配置的环境变量
LIUM_API_KEY密钥Lium API key from https://lium.io (or run `lium init` once instead)

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypilium.io0.34.2

工具

6

收录的工具列表 · 更新于 今天

参数类型必填说明
limitinteger否
gpu_typeany否
gpu_countany否

详细介绍

Lium — Python SDK 和 CLI

lium.io 是一个 Python 包,提供命令行界面和 Python SDK,用于管理 Lium 平台上的 GPU Pod。安装一次,即可根据任务选择合适的界面。

Lium 标志

Lium

快速入门   •   网站   •   CLI 文档   •   SDK 文档   •   Discord

Lium

安装

Python 包
pip install lium.io
二进制安装(macOS amd64/arm64 / Linux amd64/arm64)
curl -fsSL https://lium.io/install.sh | bash

全新安装的二进制文件会在 ~/.lium/bin/lium 创建一个由工具管理的符号链接,指向 ~/.lium/versions/<version>/lium 下带版本号的二进制文件。

快速入门

CLI
# First-time setup: create an account (mints and stores an API key) …
lium signup --email [email protected]
# … or link an existing account (opens a browser). Headless (agents, CI, containers): pass the key
# instead — lium init --api-key sk_...   (keys: https://lium.io/api-keys), or export LIUM_API_KEY and skip init.
lium init
lium balance

# List available nodes (GPU machines)
lium ls

# Price a job on node #1 before renting it (no API key needed)
lium quote 1 --hours 2

# Create a pod using node index
lium up 1  # Use node #1 from previous ls

# Or create a pod using filters
lium up --gpu A100  # Auto-select best A100 node

# List your pods
lium ps
lium ps --filter status=RUNNING --sort spent   # running pods, most expensive so far first
lium spend                                     # burn per hour, spend per pod, runway

# Copy files to pod
lium scp 1 ./my_script.py

# SSH into a pod
lium ssh <pod-name>

# Stop a pod — billing is per second and runs until you do this
lium rm <pod-name>
Pod 上的第一个小时

在刚租用的 Pod 上,有几件事可以帮你节省时间(完整版本见 docs/getting-started.rst):

  • 使用 lium up 时务必指定 --ttl(或 --until);Pod 会持续计费,直到被移除。
  • Pod 的本地卷(标准模板中的 /root;SDK 中的 pod.volume_path)是 lium bk 唯一可以备份的路径,也是加密功能覆盖的路径;挂载的卷位于 /mnt;其他所有位置(/workspace、/tmp)都是普通的容器文件系统,既未加密,也无法备份。将权重、数据集和 Hugging Face 缓存放在卷上:mkdir -p /root/hf /root/logs; export HF_HOME=/root/hf HF_HUB_ENABLE_HF_TRANSFER=1。
  • Ubuntu 24.04 镜像:使用 venv(python -m venv /root/venv),或在执行 pip install 前运行 export PIP_BREAK_SYSTEM_PACKAGES=1。
  • Blackwell GPU(B200、B300、RTX PRO 6000、RTX 5090)需要 cu128+ 的 PyTorch 构建版本:pip install torch --index-url https://download.pytorch.org/whl/cu130。FlashAttention-3 仅支持 Hopper;在 Blackwell 上请使用 FlashAttention-4 或 cuDNN attention。
  • 缺少工具时:apt-get update && apt-get install -y ffmpeg rsync。
  • 后台任务:nohup setsid cmd > /root/logs/x.log 2>&1 < /dev/null &。
  • 检查利用率:nvidia-smi --query-gpu=timestamp,index,utilization.gpu,memory.used --format=csv -l 5 > /root/logs/gpu.csv &。
SDK

SDK 以编程方式提供与 CLI 相同的功能。它有两个入口:@lium.machine 装饰器,可快速卸载独立函数;以及 Lium() 客户端,适用于长期运行的编排代码。 高级装饰器 — 为函数添加注解,并将工作交由 GPU Pod 执行。machine 的格式为 "<count>x<gpu>" 或 "<gpu>"("1xH200"、"A100"、"2xRTX4090";数量默认为 1;GPU 名称采用 lium ls --gpu 接受的格式,并进行完整匹配,因此 "A100" 绝不会租用 RTX A1000);系统会租用符合条件且价格最低的节点;timeout=(默认为 1 小时)会限制运行时长和 Pod 生命周期。参数以 pickle 格式传输(你自行提供字节,并在自己的 Pod 上加载);结果则通过 JSON 信封和 .npz 辅助文件返回,numpy 数组以 allow_pickle=False 读取,因此 Pod 写入的任何内容都不会在你的机器上反序列化。支持往返传输的类型:None/bool/int/float/str/bytes、由这些类型组成的 list/tuple/set/frozenset/dict、datetime/date/time/timedelta、Decimal、pathlib.Path、uuid.UUID、numpy.ndarray(任意不含 Python 对象的 dtype)和 numpy 标量 — 其他任何类型都会在 Pod 上触发 lium.ResultEncodingError,并指出类型名称(请改为返回 .tolist()、dict(x) 或 x.value)。只会发送函数本身的 def,因此请在函数内导入模块,并将其他所有内容作为参数传入。远程异常会以其类型重新抛出(如果该类型是内置类型,except ValueError 即可捕获;其他类型会以名称随 lium.RemoteExecutionError 一同传回),并将 lium.RemoteExecutionError(远程回溯、退出代码、输出)作为其原因:

import lium

@lium.machine(machine="A100", requirements=["torch", "transformers", "accelerate"])
def infer(prompt: str) -> str:
    from transformers import AutoTokenizer, AutoModelForCausalLM
    tokenizer = AutoTokenizer.from_pretrained("sshleifer/tiny-gpt2")
    model = AutoModelForCausalLM.from_pretrained("sshleifer/tiny-gpt2", device_map="cuda")
    tokens = tokenizer(prompt, return_tensors="pt").to("cuda")
    out = model.generate(**tokens, max_new_tokens=50)
    return tokenizer.decode(out[0], skip_special_tokens=True)

print(infer("Who discovered penicillin?"))

keep_warm=300 会让 Pod 保持 5 分钟,以供下一次调用或脚本的下一次运行使用;infer.map(prompts) 会在一个 Pod 上运行每个项目;infer.local(...) 会在本地运行函数(local=True / LIUM_MACHINE_LOCAL=1 会让每次调用都在本地运行);infer.close() 会移除保持温热的 Pod。进度信息会输出到 stderr(使用 quiet=True 可静默输出):

[lium] infer: renting 1xA100 $1.20/h (swift-fox-c8, US), removal in 1.2h
[lium] infer: pod ready in 48s
[lium] infer: preparing environment (3 package(s): torch, transformers, accelerate)
[lium] infer: environment ready in 21s
[lium] infer: running
[lium] infer: done in 96s (~$0.0320)
[lium] infer: pod removed

直接使用 SDK 时遵循相同模式:

from lium.sdk import Lium

lium = Lium()
# the cheapest available 1×A100 with at least 32 CPUs, chosen and rented in one call
rented = lium.rent(gpu_type="A100", min_cpus=32, name="demo")
print(f"{rented.executor.huid} at ${rented.price_per_hour:.2f}/h")
ready = lium.wait_ready(rented.pod, timeout=600)   # None only if still starting after 600 s
print(lium.exec(ready, command="nvidia-smi", timeout=60)["stdout"])
lium.down(ready)

当 Pod 达到 FAILED/CREATION_FAILED/STOPPED/BROKEN 状态或从 Pod 列表中消失时,wait_ready() 会抛出 PodStartError,其中包含 .pod、.status、.history 和 .cause(后端记录的信息,例如 Container creation failed due to ... (failure_step: ssh_connect)),因此不会把已失效的 Pod 误认为只是启动较慢。传入 on_poll=lambda pod, status, elapsed: ...,即可获知每次轮询的结果。lium up 会通过 --timeout SECONDS(默认 900)限制整个租用过程;等待期间会输出 waiting for <pod>… <STATUS> (<n> s),超出时限后会以 1 退出并指出 Pod 名称;--ready-timeout 仅限制等待时长。

长时间运行的任务会在由调用方保留的 Pod 上执行:detach=True 会在后台启动任务并立即返回,Pod 会持续运行,直到你将其移除。需要指定节点时,可通过 lium.ls() 列出节点;up(wait=True) 会租用该节点并返回已就绪的 Pod。

node = lium.ls(gpu_type="A100")[0]
pod = lium.up(executor_id=node.id, name="train", wait=True)
job = lium.exec(pod, command="python train.py", detach=True)   # {"pid", "log_path", "command"}
for gpu in lium.gpu_stats(pod):                                  # parsed nvidia-smi
    print(gpu.index, gpu.utilization_pct, gpu.memory_pct)
print(pod.to_dict())                                             # JSON-ready
# later: lium.down(pod)

如果工作不应超出使用它的代码的生命周期,rental() 会为 with 代码块租用一个指定名称的节点,并在退出代码块时移除 Pod,无论代码块内部发生什么 — 因此应在代码块内运行完整任务(在此处启动的分离任务会随 Pod 一同被终止)。上面的 rent() 是另一种方式:它会根据规格选择节点,并交给你一个由你拥有的 Pod。

with lium.rental(executor_id=node.id, name="eval") as pod:
    result = lium.exec(pod, command="python eval.py", timeout=1800)
    print(result["stdout"])

lium.pod_by_name("job") 可通过名称、huid 或 id 查找 Pod。

服务器或训练任务的生命周期应长于启动它的调用。run_background() 会以分离模式启动任务,并在 Pod 上创建 PID 文件、退出代码文件和日志(还会在 .id 文件中记录进程的启动 ID 和开始时间,因此 status() 和 kill() 绝不会误将 Pod 重启后复用的 PID 当作该任务;没有此文件的任务会显示为 gone,且不会收到信号);返回的 Job 知道如何等待任务:

job = lium.run_background(pod, "vllm serve Qwen/Qwen3-8B --port 8000", name="vllm")
job.wait_for_port(8000, timeout=900)   # raises at once, with the log tail, if vllm dies first
print(job.logs(tail=20))
# later, from another process or agent turn:
job = lium.job(pod, "vllm")            # re-attach by name; job.status(), job.kill()

lium.wait_for_port(pod, 8000) 可在没有任务的情况下探测端口(例如启动时提供服务的模板);lium.wait_ready(pod, ready_port=8000) 会同时等待 Pod 进入 RUNNING 状态并确认端口就绪。 多节点集群 — 在同一 InfiniBand/RoCE 网络上租用 N 个完整节点,作为一个订单处理,每个节点都有一个专用覆盖网络地址:

offer = lium.clusters()[0]                                   # fabrics with free nodes
cluster = lium.up_cluster([n.id for n in offer.cheapest(2)], name="train", wait=True)
print(cluster.master_addr)                                   # 10.42.0.1 — MASTER_ADDR for torchrun
for pod in cluster.pods:
    lium.exec(pod, command=f"torchrun {cluster.torchrun_args(pod)} --nproc_per_node 8 train.py")
open("hostfile", "w").write(cluster.hostfile())              # mpirun / DeepSpeed
lium.rm_cluster(cluster)                                     # one DELETE /clusters/{id}; one result per member

当节点已租用或可能已租用,但 Pod 列表未显示完整集群时,up_cluster() 会引发 ClusterNotListedError(.confirmed 表示 API 是否确认了订单,.pod_ids 和 .listed 分别表示 API 命名的 Pod 和列表中显示的 Pod):不要再次租用,请列出 Pod 以查找集群。只要有成员失败或未出现在 Pod 列表中,wait_cluster_ready() 就会立即引发 PodStartError。rm_cluster() 会发送一个 DELETE /clusters/{cluster_id}:API 会移除所有成员,并为每个成员返回一行(pod、huid、name、node_rank、success、message、error);移除失败的成员会在结果中报告,其余成员仍会被移除,因此可再次调用以重试。若返回 404(集群已不存在,或 API 没有此路由),则会引发 LiumNotFoundError,且不会移除任何内容;不会逐个 Pod 回退处理。

完整 API 参考:https://docs.lium.io/developers/sdk/reference

lium.ssh(pod) 会返回 Pod 的 SSH 命令,其中包含 -i <key> 和 Configuration 中所述的固定主机密钥选项;重启后传入 refresh=True,即可根据 Pod 当前的主机和端口重新生成命令(lium.refresh_pod(pod) 会按 ID 或 huid 重新读取单个 Pod;若 Pod 已不存在,则会引发 LiumNotFoundError)。lium ps --format json 和 lium describe(表格及 --json)会以 ssh_command 的形式显示相同的命令,但不包含 -i(密钥路径存储在 SDK 配置中,而不在 Pod 记录中);JSON 会将 API 的原始值保留为 ssh_cmd。

文档

二进制版本

  • 支持的二进制目标:darwin-amd64、darwin-arm64、linux-amd64、linux-arm64
  • 维护者可使用 bash scripts/build.sh [macos|linux|all] 在本地构建(Linux 构建通过 Dockerfile.build 完成)
  • 版本通过 vX.Y.Z 标签发布为 GitHub 版本(.github/workflows/release.yml):版本号即标签(hatch-vcs;仓库中无需修改任何内容),工作流会构建四个二进制文件及其 .sha256 校验和,将它们(以及 install.sh、合并后的 checksums.txt 和 sdist/wheel)上传到版本页面,随后清除预发布标记;另一个独立任务会在 Python 构建通过后立即将 sdist/wheel 发布到 PyPI,不受二进制文件构建进度影响。创建版本时请使用 --prerelease,以免资源文件上传完成前 latest 就指向该版本。
  • 变更以片段形式记录在 changelog.d/ 中(每个 PR 一个文件,文件名使用对应的工单名;参见 changelog.d/README.md),并由 scripts/changelog.py 在发布时汇总到 CHANGELOG.md。

CLI 参考

lium CLI 提供完整的 Pod 生命周期管理功能。运行 lium --help 查看所有内容,或浏览以下参考文档。

核心命令
  • lium signup - 在终端创建账户并保存其 API 密钥
  • lium init - 为现有账户初始化配置(API 密钥、SSH 密钥);对于没有浏览器的机器,使用 --api-key <key>;使用 --force 重新登录
  • lium completion [bash|zsh|fish] [--install] - 打印或安装 Shell 补全
  • lium balance - 显示账户余额(添加 --format json 可输出机器可读格式)
  • lium whoami - 显示正在使用的 API 密钥、其来源以及所属账户
  • lium ls [--gpu TYPE] [--count N] [--country CODE] [--min-vram GB] [--max-price USD] [--tier spot|secure] [--format json] - 列出可用节点
  • lium up [NODE_ID] - 创建 Pod(NODE_ID 是 lium ls 输出中的 HUID 或 UUID,也可以是行号;也可使用 --gpu、--count、--country 等筛选条件;使用 --ttl 6h 或 --budget 12.50 设置上限;--json 会以 JSON 格式输出已就绪的 Pod,而不是打开 SSH)
  • lium ps [--sort KEY] [--filter KEY=VALUE] [--key NAME|ID] [--watch N] [--wide] [--format json] - 列出活动 Pod;# 列是行号,rm/ssh/exec/scp 可在同一个 Shell 中接受该行号,有效期为 10 分钟,且仅当该行显示的 Pod 仍在列表中时有效——即上次列表中的行,顺序与显示顺序相同(可能经过排序或筛选)。脚本中请使用 huid。对于 PENDING Pod,表格下方会显示后端提供的启动预计时间和阶段,并使用与 lium up 相同的措辞(eager-wolf-aa PENDING · est. ready in ~18 s (phase: pulling image));其 --format json 行会在 eta_hint 中包含相同文本(后端未提供两者时为 null)。
  • lium spend [--format json] - 每小时消耗、每个 Pod 的预估支出、余额和可维持时长
  • lium record <pod> [--format json] - 显示一次运行使用的配置(GPU、镜像、驱动程序/CUDA、互连)及费用;Pod 删除后仍可使用其 UUID 查询
  • lium quote <node> --hours N [--gpus N] [--volume-gb N] [--backup-gb N] [--format json] - 租用前,按计费费率计算作业在某个节点上的计算、存储卷和备份费用
  • lium describe <POD> - 显示单个 Pod 的完整清单:端口、GPU、模板、计费信息、最近的生命周期事件(为何出现 REBOOT_FAILED/BROKEN)以及节点的磁盘健康状况(添加 --json 可输出机器可读格式)。已删除的 Pod 仍可通过其 ID 查询:你可以看到后端为其保留的事件以及 Pod 消失的原因。
  • lium ssh <POD> - 通过 SSH 连接到 Pod
  • lium exec <POD> <COMMAND> - 在 Pod 上执行命令(--json 用于输出 stdout/stderr/exit_code;-d/--detach 会在后台启动命令并立即返回;--max-output-bytes N 设置输出上限,默认值为 64 MiB)
  • lium logs <POD> - 流式查看 Pod 的容器日志
  • lium port-forward <POD> <PORT> - 将本地端口转发到 Pod 端口
  • lium scp <POD> <LOCAL_FILE> [REMOTE_PATH] - 将文件复制到 Pod(添加 -d 可从 Pod 下载)
  • lium rsync <POD> <LOCAL_DIR> [REMOTE_PATH] - 将目录同步到 Pod(支持 --bwlimit、--exclude、--delete、--progress;重新运行时会续传)
  • lium cp <SRC_POD>:<PATH> <DST_POD>:<PATH> - 通过 SSH 将文件从一个 Pod 复制到另一个 Pod
  • lium rm <POD> - 删除/停止 Pod(在脚本中添加 --name-only 可拒绝 lium ps 行号;--format json 会输出已删除的内容及其预估支出;--rating 1-5 --feedback "..." 可在同一次调用中为节点评分)
  • lium reboot <POD> - 重启 Pod
  • lium reset-gpu <POD> [--gpu N ...] - 重置卡住的 Pod GPU;会停止 Pod 进程,但保留其文件;等待 1-2 min 获取结果
  • lium audit [--pod POD] [--since 24h] [--key ID] - 查看谁在何时对账户的 Pod 执行了什么操作:每次租用、重启、编辑和删除,以及发起操作的会话或 API 密钥(添加 --json 可输出机器可读格式)
  • lium audit --account [--action pod.] [--source cli] [--since 7d] [--cursor <next_cursor>] - 账户审计日志:每个更改内容的请求(Pod、密钥、登录、余额、设置、团队成员),以及发起请求的客户端和 IP;仅包含你自己的 IP,保留 90 天(--json 会输出包含 next_cursor 的页面)
  • lium update <POD> --jupyter <PORT> - 在 Pod 上安装 Jupyter Notebook,并通过指定的内部端口提供服务(--jupyter 是唯一支持的更新项;不指定时,命令会输出 No updates specified)
  • lium templates [SEARCH] [--arch hopper|blackwell] [--format json] - 列出 Docker 模板,以及其 CUDA 构建版本和支持的 GPU 世代
  • lium fund - 使用钱包中的 TAO 为账户充值(--alpha -k <hotkey> -a <USD> 可改用 alpha 质押付款;添加 --netuid <N> 可从 Lium 接受的任意子网付款,否则使用主子网)
  • lium topup create -a <USD> -c <COIN> -n <NETWORK> - 使用稳定币充值(lium topup currencies 可列出支持的稳定币)
  • lium topup card -a <USD> [--card <pm_id>] [--yes] - 使用保存在账户中的银行卡扣款,无需浏览器;API 密钥需要 billing 作用域(尚未发布:平台开关已关闭)。默认会先询问;--yes 可跳过询问,且使用 --json 时必须添加该选项。请求只发送一次,并带有幂等密钥;如果响应丢失,或返回不带 payment_intent_id 的 202,则以退出码 6 结束(“扣款可能已成功”/“仍在确认中”),并给出密钥和可用于重新运行的相同金额,绝不会不带密钥重试。带有 payment_intent_id 的 202 表示成功(退出码 0)。相同密钥搭配不同金额会发起新的扣款。3-D Secure 追加验证(CARD_AUTHENTICATION_REQUIRED,附带 URL)会以退出码 6 结束,并给出确认 URL、交易 ID,以及使用相同 --idempotency-key 重新运行的完整命令;使用新密钥会发起第二笔付款
  • lium ssh-keys list|sync - 列出或同步注册到账户的 SSH 公钥 ls、ps、spend、templates、balance 和 describe 都支持 --format json(以及 --json);rm 支持 --format json;up 支持 --json。如果命令失败,它们都会在 stderr 上输出 JSON 错误信封,因此脚本中可以在不同命令间使用相同的标志。
卷命令
  • lium volumes list - 列出所有卷
  • lium volumes new <NAME> - 创建新卷
  • lium volumes rm <TARGETS> - 按 HUID 或 id 移除卷,也可按上次 lium volumes 列表中的行号移除(1 或 1,3);行号需要来自同一 shell 中、且不超过 10 分钟前的列表,否则命令会要求你重新列出
集群命令
  • lium clusters - 列出有空闲节点、可租用为一个多节点集群的 Fabric(InfiniBand/RoCE)
  • lium clusters up <FABRIC> --nodes N -n <NAME> - 将同一 Fabric 的 N 个整节点租用为单个全有或全无的集群
  • lium clusters ps - 列出你的集群
  • lium clusters show <CLUSTER> [--hostfile | --torchrun RANK] - 显示成员及其 rank、overlay IP 和 SSH;提供启动器所需内容
  • lium clusters rm <CLUSTER> - 在一次 API 调用中移除所有成员(集群已不存在时退出码为 5)
备份命令
  • lium bk show <POD> - 显示 pod 的备份配置
  • lium bk set <POD> --path <PATH> - 配置自动备份
  • lium bk logs <POD> - 查看备份日志
  • lium bk now <POD> - 立即触发备份
  • lium bk cancel --id <BACKUP_ID> - 取消正在进行的备份并保留其历史记录
  • lium bk delete --id <BACKUP_ID> - 删除已完成备份的存储数据
  • lium bk restore <POD> --id <BACKUP_ID> - 从备份恢复
  • lium bk restore-cancel --id <RESTORE_ID> - 取消正在进行的恢复
  • lium bk rm <POD> - 移除备份配置
计划命令
  • lium schedules list - 列出计划终止任务
  • lium schedules rm <POD> - 取消计划终止任务
工作区命令

团队共用一个工作区,由其计费所有者付款。API 密钥绑定到一个工作区,因此任何命令上的 --workspace NAME 都表示“使用为 NAME 保存的密钥”,仅此而已。在不支持工作区的服务器上,这些命令会说明这一点(退出码为 3),其他所有命令的行为则与目前相同。

  • lium workspaces [list] - 此密钥执行操作的工作区(显示的角色是该密钥所用账户的角色;对于团队密钥,则是账单所有者的角色);运行 lium workspaces login 后,列出你所属的每个工作区及你自己的角色
  • lium workspaces members [WORKSPACE] - 成员、角色以及付款方
  • lium workspaces use <WORKSPACE> - 设置所有命令的默认工作区(~/.lium/config.ini);运行 LIUM_API_KEY=<a key bound to it> lium workspaces use <WORKSPACE>,可保存该密钥供 --workspace 使用
  • lium workspaces login - 登录一次(电子邮件 + 密码),以使用下文中仅限当前会话的子命令;无需 API 密钥,且未保存任何密钥时,lium keys 仅在当前会话中运行
  • lium workspaces create <NAME> [--use] - 创建工作区;你是其所有者和账单所有者
  • lium workspaces invite <EMAIL> [WORKSPACE] [--role member|admin|owner] - 通过电子邮件发送邀请(对方目前无需账户)
  • lium workspaces remove <USER_ID_OR_EMAIL> [WORKSPACE] [--yes] - 移除成员,会先询问确认(所有者和账单所有者不能被移除;服务端会说明原因)
  • lium workspaces transfer-billing <USER_ID_OR_EMAIL> [WORKSPACE] [--yes] - 将账单转交给另一位成员(会先询问确认)
  • lium workspaces delete [WORKSPACE] [--yes] - 删除工作区,会先询问确认(所有者可执行;有运行中的 pod 或存在卷时会拒绝);删除其配置区段
  • lium keys list [--workspace W] / lium keys create <NAME> [--scope read|rent|manage|billing]… [--daily-budget USD] [--monthly-budget USD] [--max-budget USD] [--pod-visibility own|account] [--workspace W] [--save] - 管理每个工作区的 API 密钥;--save 会保存密钥供 --workspace 使用。未指定 --scope 时,密钥将获得 read、rent、manage 权限;只有明确指定时才会授予 billing 权限(通过 API 进行卡支付、信用额度转账和加密货币支付),且会先显示警告,并且必须单独指定:与其他任何权限同时使用 --scope billing 会在发送任何请求之前被拒绝(退出码为 2)。预算包括按 UTC 日、按 UTC 月以及密钥有效期内的预算;达到预算后会删除该密钥的 pods(卷外的数据会丢失),并拒绝通过该密钥租用 pod、更改 pod 计划或充值(budget_exceeded,退出码为 6,并指出触发限制的预算周期);--pod-visibility own 仅显示该密钥租用的 pods,account 则显示所有 pod;未传入时由服务端默认值决定。list 会显示权限范围、各周期的已用金额和预算,以及每个密钥的活动 pods。--scope billing 及其资金路径规则(通过 API 进行卡支付、信用额度转账和加密货币支付需要持有 billing 权限的密钥)、预算、可见性和 pod 数量均需要较新版本的 Lium 服务端。若服务端无法记录所请求的预算、可见性或 pod 数量(各项分别判断),create 会拒绝创建(退出码为 2;服务端签发的未设上限密钥会被撤销),除非传入 --allow-unbudgeted
  • lium keys show <NAME|ID> / lium keys scopes - 显示单个密钥及服务端所用措辞的“此密钥可执行的操作”(GET /keys/scopes)、各周期的已用金额和预算、该密钥的 pods,以及其预算拒绝的最近请求(GET /keys/{id}/refusals:今天拒绝的次数、最新一次请求的路由、金额和周期)/ 显示所有权限范围和 pod 可见性值及其允许的操作。两者都需要较新版本的 Lium 服务端:旧版本会对 scopes 返回 not_found,并且在 show 中仅显示权限范围名称
  • lium keys budget <NAME|ID> [--daily-budget USD] [--monthly-budget USD] [--max-budget USD] [--no-daily-budget] [--no-monthly-budget] [--no-max-budget] - 创建密钥后设置或清除其预算(PATCH /keys/{id};至少为 $1,以整分为单位,且 daily ≤ monthly ≤ max;未指定的预算保持不变)。权限范围和 pod 可见性在创建时确定,之后保持不变。需要支持每密钥预算的服务端(旧版本没有此路由;若尝试设置其未记录的预算周期,则会被拒绝,退出码为 2)
  • lium ps --key <NAME|ID> / lium billing history [--key <NAME|ID>] [--from YYYY-MM-DD] [--to YYYY-MM-DD] [--format json] - 查看由一个 API 密钥租用的 pods / 查看账本按 pod 计收的费用,包括已移除的 pods;可查询账户或某个密钥(GET /billing/statement)。按密钥筛选需要支持为 pods 和费用标记密钥的服务端:旧版本无法筛选,这两个命令都会说明原因,并显示账户整体数据。密钥名称需要通过 lium workspaces login 才能使用;密钥 ID 则不需要
  • lium --workspace NAME <command> / LIUM_WORKSPACE=NAME - 使用为 NAME 保存的密钥运行单个命令(若未保存密钥,则会拒绝,退出码为 2);ps、ls、up、rm 会打印其操作所针对的工作区;若该密钥实际操作的是其他工作区,up / rm 会拒绝执行(退出码为 2),而 ps / ls 会发出警告。lium workspaces … 和 lium keys … 本身会依次使用 LIUM_API_KEY、NAME 保存的密钥、已存储默认工作区保存的密钥,最后使用 [api] api_key;因此它们可以创建或保存缺失的密钥
配置命令
  • lium config show - 显示所有配置
  • lium config get <KEY> - 获取配置值
  • lium config set <KEY> <VALUE> - 设置配置值
  • lium config unset <KEY> - 移除配置项
  • lium config edit - 编辑配置文件
  • lium config path - 显示配置文件路径
  • lium config reset - 重置所有配置
Provider 命令

lium provider … 是 Provider 端的命令行工具,与 lium.io/portal 的前端功能完全一致,可用于自动化:Portal 身份验证、节点生命周期管理、central-miner-server 配置、批量同步、计费和机器请求查询。Hotkey 注册仍需单独通过 btcli subnet register 处理。

每个子命令都会继承以下组级标志:-w/--coldkey、-k/--hotkey、--portal-url、--json、--debug、-y/--yes、--dry-run。通过 lium config set provider.coldkey <NAME> 和 lium config set provider.hotkey <NAME> 保存一次钱包身份。除非设置了 --yes 或 LIUM_PROVIDER_ACK=1,可能产生支出的子命令都会提示确认。

不使用密钥的账户(Google 或电子邮件): 在 Portal 中创建 API 令牌(账户设置中的 API 令牌;尚未发布),然后运行 export LIUM_PROVIDER_TOKEN=lpk_...(或通过 lium provider portal login --token 保存);之后运行 lium provider 命令无需指定 --hotkey。电子邮件账户也可以运行 lium provider portal login --email <address>。

  • lium provider portal {login,logout,whoami} - 管理缓存的 Portal JWT
  • lium provider status [--netuid 51] - 汇总 Provider 状态快照(注册状态、Portal 会话、节点、验证器权重)
  • lium provider node list|get|add|rm|update-price|update-gpu|address - 在 Portal 中管理节点生命周期;默认情况下,node list [--all | --miner-hotkey HK] 会显示当前活跃 Hotkey 的节点,--all 则显示所有 Provider 的节点
  • lium provider node address <NODE_ID> <IP> <PORT> - 原位更改节点的 IP 和端口(保留其 ID 和历史记录),例如 ISP 更改 IP 后
  • lium provider node min-gpu set|unset <NODE_ID> [COUNT] - 设置租用匹配所需的最低 GPU 数量
  • lium provider node pods <NODE_ID> - 查看当前租用该节点的 Pod
  • lium provider node machine-requests <NODE_ID> - 查看节点上待处理的租户请求
  • lium provider node notice-period set <NODE_ID> --start <ISO 8601> --minutes N | --permanent [--reason TEXT] - 开启通知期:最长 60 分钟的维护窗口,或永久移除
  • lium provider node notice-period unset <NODE_ID> - 结束节点的通知期
  • lium provider node notify-added <NODE_ID> --request-id <REQ> - 标记已满足租户机器请求
  • lium provider config show|opt-in|opt-out|set-email|set-subscriptions - 管理 Portal 账户配置(包括 lium.io central miner server 开关)
  • lium provider sync from-miner-server|to-miner-server - 在 Portal 与 central miner server 之间批量同步节点状态
  • lium provider billing list [--from YYYY-MM-DD] [--to YYYY-MM-DD] - 查看每日收入账单(仅显示已登录 Provider 自身的记录;默认显示最近 30 天,最多 90 天)
  • lium provider machine-request list|get - 查看待处理的租户机器请求(只有当验证器验证了你的某个节点后,才会显示单个请求的详细信息;在此之前,list 会按 GPU 类别和每小时预算区间返回数量,get 会以 PORTAL_FORBIDDEN 退出,状态码为 2)
  • lium provider machine list|estimate - 查看机器目录和奖励估算

完整参考文档(含所有标志和可运行示例):https://docs.lium.io/developers/cli/reference/provider。

其他命令
  • lium mcp - 通过 stdio 将 Lium 作为 MCP 服务提供给 Agent 主机(pip install "lium.io[mcp]";参见面向 Agent 主机的 MCP 服务)
  • lium theme dark|light - 设置 CLI 颜色主题(必须提供参数;没有 auto;该值存储为 [ui] theme,可通过 lium config get ui.theme 读取)
  • lium mine - 将此主机设置为提供方节点
  • lium mine --register <TOKEN> - 同上,然后根据主机报告的信息将节点添加到你的门户账户,并等待节点出现在列表中(令牌来自门户的 Add Node 页面;账户以及节点报告所属的账户均由令牌决定;不使用 -k)
  • sudo lium gpu-splitting setup [--device /dev/...] [--yes] - 为 LIUM GPU 分割准备 Docker 存储
  • lium gpu-splitting check [--device /dev/...] - 检查主机并输出 GPU 分割计划
  • lium gpu-splitting verify - 验证 Docker 存储是否符合 LIUM GPU 分割要求
命令示例
# Filter nodes
lium ls --gpu H100
lium ls --gpu H100 --count 8 --country US,NL --max-price 2.50
lium ls --min-vram 80 --min-cuda 12.8 --tier secure
lium ls --format json          # machine-readable

# Multi-GPU jobs: only nodes whose GPUs are all on NVLink (Link column NV#), and a floor on
# the Download (Mbps) column — tensor parallelism and 700 GB checkpoints behave very
# differently on a PCIe box or a slow link that the price does not reveal
lium ls --gpu H200 --nvlink --min-download 2000

# Skip nodes whose rents often fail to start
lium ls --gpu H100 --reliable

# Create pod with node index
lium up 1 --name my-pod --yes

# Create pod with filters (auto-selects best node)
lium up --gpu A100 --count 8 --name my-pod --yes
lium up --gpu H200 --country US

# Create pod with specific template
lium up 1 --template_id <TEMPLATE_ID> --yes

# Set up node bootstrap flow
lium mine --auto --hotkey <HOTKEY>

# One command from a bare host to a listed node: the portal's Add Node page prints this line with a
# one-hour token; GPU model/count, port and address are read from the host, the price is the portal base price for the model
curl -fsSL https://lium.io/mine.sh | bash -s -- --register <TOKEN>
lium mine --register <TOKEN> --wait 0          # add the node, do not wait for the validator

# Node behind CGNAT or a port-forwarding VPS: register the VPS address and forwarded port
lium mine --auto --hotkey <HOTKEY> --ip <VPS_IP> --external-port <FORWARDED_PORT> --internal-port 8080

# Provider-portal automation (same surface as the portal frontend)
lium config set provider.coldkey miner-prod        # one-time: persist wallet identity
lium config set provider.hotkey  miner-1
lium provider portal login                         # JWT exchange via hotkey signature
lium provider status                               # registration, portal session, nodes, weights
lium provider node list --limit 50
lium provider node add --gpu-type "NVIDIA H200 NVL" --gpu-count 8 \
    --ip 203.0.113.42 --port 8080 --price 1.85 --yes
lium provider node update-price <NODE_ID> --price 2.10 --yes
lium provider node address <NODE_ID> 203.0.113.77 8080 --yes
lium provider config opt-in --yes                  # use lium.io's central miner server
lium provider machine estimate --gpu-type "NVIDIA H200 NVL" --gpu-count 8
lium provider --json status                        # JSON envelope for scripts/agents

# Inspect or configure Docker storage for GPU splitting (Ubuntu/Debian + systemd, run setup as root)
lium gpu-splitting check
sudo lium gpu-splitting setup --yes
lium gpu-splitting verify

# Create pod with volume
lium up 1 --volume id:<VOLUME_HUID>
lium up 1 --volume new:name=mydata,desc="My dataset"

# Create pod with auto-termination
lium up 1 --ttl 6h                    # Terminate after 6 hours
lium up 1 --budget 12.50              # Terminate once $12.50 has been spent
lium up 1 --until "today 23:00"       # Terminate at 11 PM today

# Create pod without the automatic volume backup
lium up 1 --no-backup

# Create pod with Jupyter
lium up 1 --jupyter --yes

# Fail (non-zero exit) if the pod exposes a different GPU count than requested or billed
lium up --gpu H200 --count 8 --verify-gpus --yes          # also counts GPUs with nvidia-smi over SSH
lium up --gpu H200 --count 8 --verify-gpus --strict-gpus  # ...and remove the pod on mismatch

# Execute commands
lium exec my-pod "nvidia-smi"
lium exec my-pod "python train.py"

# Start a long job in the background and return immediately (prints PID and log path)
lium exec my-pod -d "python train.py"                      # log: /workspace/logs/exec-<timestamp>-<id>.log
lium exec my-pod -d --log /workspace/train.log --script train.sh
lium exec my-pod "tail -n 200 /workspace/train.log"        # exec returns output when the command exits, so read a bounded slice

# Copy files to and from pods
lium scp my-pod ./script.py                    # Copy to /root/script.py
lium scp 1 ./data.csv /root/data/             # Copy to specific directory
lium scp all ./config.json                    # Copy to all pods
lium scp 1,2,3 ./model.py /root/models/       # Copy to multiple pods
lium scp my-pod /root/output.log ./downloads -d  # Download into ./downloads directory

# Reboot pods
lium reboot my-pod                           # Reboot a single pod
lium reboot 1,2                              # Reboot pods 1 and 2 (no confirmation prompt)
lium reboot all                              # Reboot all active pods
lium reboot my-pod --volume-id <VOLUME_ID>   # Reboot with a specific volume ID

# Sync directories to pods
lium rsync my-pod ./project                    # Sync to /root/project
lium rsync 1 ./data /root/datasets/           # Sync to specific directory
lium rsync all ./models                       # Sync to all pods
lium rsync 1,2,3 ./code /root/workspace/      # Sync to multiple pods
lium rsync my-pod ./ckpt /workspace/ckpt --bwlimit 20000 --exclude '*.tmp' --progress
                                              # Throttled, filtered, with progress; re-run to resume

# Copy between pods directly (data never passes through your machine)
lium cp dev-pod:/workspace/src train-pod:/workspace/
lium cp 1:/workspace/ckpt/ 2:/workspace/ckpt/ --exclude '*.tmp'

# Remove multiple pods
lium rm my-pod-1 my-pod-2
lium rm all  # Remove all pods

# Install Jupyter on existing pod (internal port 8888)
lium update my-pod --jupyter 8888

# Manage volumes
lium volumes list
lium volumes new mydata --desc "My dataset"
lium volumes rm 1                              # row 1 of the list above (same shell, under 10 minutes old)
lium volumes rm noble-matrix-27                # or by HUID / id

# Multi-node clusters
lium clusters                                  # fabrics with free nodes
lium clusters up 1 --nodes 2 -n train --ttl 6h # 2 whole nodes of fabric #1, one order
lium clusters show train --hostfile            # 10.42.0.1 slots=8 / 10.42.0.2 slots=8
lium clusters show train --torchrun 1          # --nnodes 2 --node_rank 1 --master_addr 10.42.0.1 --master_port 29500
lium clusters rm train -y

# Manage backups
lium bk show my-pod
lium bk set my-pod --path /root/data --every 24h --keep 7d
lium bk logs my-pod
lium bk now my-pod --name manual-backup
lium bk cancel --id <BACKUP_ID>
lium bk delete --id <BACKUP_ID>
lium bk restore my-pod --id <BACKUP_ID> --to /root/restore
lium bk restore-cancel --id <RESTORE_ID>
lium bk rm my-pod

# Manage schedules
lium schedules list
lium schedules rm my-pod

# Configuration management
lium config show
lium config get api.api_key
lium config set ssh.key_path /path/to/key
lium config edit

# Theme management
lium theme dark     # Set to dark theme
lium theme light    # Set to light theme

# Fund account with TAO
lium fund                           # Interactive mode
lium fund -w default -a 1.5        # Fund with specific wallet and amount
lium fund -w mywal -a 0.5 -y       # Skip confirmation

# Fund account with alpha stake (-a is USD)
lium fund --alpha -k <hotkey> -a 25              # Lium's primary subnet
lium fund --alpha -k <hotkey> -a 25 --netuid 64  # Any subnet Lium accepts
lium ls --format json 字段

每个节点对应一个对象,排序与表格一致;名称保持稳定:

字段含义
index行号,即 lium up <index> 所使用的值
id, huid节点 UUID(API 所需)及其人类可读 ID(lium up <huid>)
config, gpu_type, gpu_count, machine_name8×H100、H100、8、NVIDIA H100 80GB HBM3
available_gpu_count节点当前空闲的 GPU 数量(服务未提供时为 null);使用 -c 租用时最多可租用此数量
price_per_gpu_hour, price_per_hour每 GPU 小时价格和整台节点的每小时价格,单位为 USD
country, country_code, city国家名称、ISO 代码、城市
vram_gb, ram_gb, cpu_count每 GPU VRAM(GiB)、主机 RAM(GiB)、CPU 线程数
disk_gb, disk_total_gb主机可用磁盘空间和总磁盘空间(GiB)
upload_mbps, download_mbps后端的有效速度:有 VerifyX 下载速度或验证器周期平均值时使用该值,否则使用节点最新的测速样本
upload_source, download_sourcemeasured(已检查或取平均值)或 reported(单次测速样本,即表格中的 ~);没有数据时为 null
available_ports可用于 --ports 的空闲端口
docker_in_dockersysbox 运行时,即可在 pod 内使用 docker run
is_pareto★ 标记
max_cuda_version驱动支持的最高 CUDA 版本
tiersecure 或 spot(可回收)
link, nvlink, p2pLink 列(NV18 = 每个 GPU 有 18 条链路的 NVLink,PCIe/SYS = 最差的 PCIe 类别);当所有 GPU 对都通过 NVLink 连接时为 true;当所有 GPU 对都通过 P2P 检查时为 true;在 Lium 报告节点拓扑之前为 null
interconnect节点的拓扑对象:配对数和链路数、pcie_class、p2p;在列表中不包含 matrix(GPU x GPU 表格位于 lium describe <pod> 中)
gpu_power_limited, gpu_power_limit_w, gpu_power_limit_default_w表格中 ↓W 标记对应的字段:当某个 GPU 的功率上限低于显卡默认值的 95% 时为 true(峰值性能可能略低);使用默认功率时为 false;平台无法判断节点时为 null;功率限制最低的 GPU 的当前和默认功率上限,单位为瓦

列表请求 GET /executors?view=summary,每个节点约 1 KB,而非约 8.6 KB。摘要视图包含 nvlink 和 interconnect 键,link、nvlink、p2p 和 interconnect 会读取这些键。Lium.ls(view="full") 会在 ExecutorInfo.specs 中返回完整的公开节点抓取数据,但不包括租用者 pod 的运行情况(Docker 容器、GPU 进程、每个 GPU 的负载、正在使用的内存、当前时钟频率和 PCIe 链路);使用 Lium.gpu_stats 读取你自己的 pod 负载。

功能

  • 双重接口:同一个包同时提供 lium CLI 和 Python SDK(lium.sdk.Lium + @lium.machine 装饰器)
  • 帕累托优化:ls 命令会显示最优节点,并用 ★ 标记
  • 灵活创建 Pod:使用节点索引,或通过筛选条件(GPU 类型、数量、国家/地区)自动选择
  • 按索引选择:在命令中使用 ls 输出中的数字
  • 全宽表格:终端输出清晰易读
  • 成本跟踪:在 ps 中查看支出和每小时费率
  • 交互式设置:使用 init 命令轻松开始
  • 卷管理:创建并挂载持久化存储卷
  • 备份与恢复:自动备份,可配置频率和保留期限
  • 自动终止:设置 Pod 在指定时长后或指定时间终止
  • Jupyter 集成:一条命令即可在 Pod 上安装 Jupyter
  • 主题支持:提供浅色、深色或自动检测主题,提升可视性

配置

配置存储在 ~/.lium/config.ini 中:

[api]
api_key = your-api-key-here

[ssh]
key_path = /home/user/.ssh/id_ed25519

也可以使用环境变量:

export LIUM_API_KEY=your-api-key-here

LIUM_API_KEY 的优先级高于配置文件。要查看 shell 当前使用的密钥,请运行 lium whoami(或 lium balance / lium config get api.api_key):它们会显示密钥指纹和来源(env:LIUM_API_KEY 或 config:~/.lium/config.ini [api] api_key),身份验证错误也会指出同一个密钥。

使用工作区时,lium workspaces use(当它运行时使用的密钥在该工作区有效)和 lium keys create --save 会添加:

[workspaces]
active = research

[workspace.research]
id = 9d8c7b6a-…
api_key = the-key-bound-to-that-workspace

# from `lium workspaces login`; LIUM_SESSION_TOKEN overrides it
[session]
token = …

密钥解析:显式指定 --workspace / LIUM_WORKSPACE 时,只使用为该工作区保存的密钥(若未保存,则以状态码 2 退出)。否则按以下顺序匹配,使用第一个匹配项:LIUM_API_API_KEY / LIUM_API_KEY(环境变量密钥,按 CLI 中的顺序)、为 [workspaces] active 保存的密钥、[api] api_key。保存密钥时会写入 [workspace.<name>] 节(使用 lium keys create --save,或在使用的密钥对该工作区有效时运行 lium workspaces use);lium workspaces delete 会将其删除。节名使用小写名称作为键,因此如果某个节中已有另一个工作区的 ID(两个工作区同名),则拒绝写入(以状态码 2 退出),而不会覆盖第一个工作区的密钥;请先删除该节或重命名其中一个工作区。

对于没有浏览器的机器——例如 Agent 的沙箱、CI 或容器——lium init --api-key <key> 会通过 /users/me 验证密钥,以模式 600 将其保存到文件,并设置 SSH 密钥;整个过程不会打开任何内容,也不会提出任何问题;--json 会输出 {"ok", "api_key_source", "saved_from", "env_key", "active_workspace", "config_path", "ssh_key_path"}——api_key_source 与 lium whoami --json 输出的值相同,表示按上述 密钥解析 顺序,下一个命令从何处读取密钥(env:LIUM_API_KEY、config:<path> [api] api_key,或 lium workspaces use 选中工作区后使用的 [workspace.<name>] 密钥——此时 active_workspace 会显示该工作区,文本输出也会警告该密钥的优先级高于刚保存的密钥);saved_from 表示本次运行通过何种方式获得密钥(flag、env、config、session、browser)。--json 需要使用 --api-key 或已导出的密钥;浏览器流程会向用户显示信息。密钥遭拒时以状态码 3 退出(invalid_api_key),无法连接 API 时以状态码 3 退出(api_unreachable),值为空时以状态码 2 退出(empty_api_key);这些情况下都不会保存任何内容,提示也会说明这一点。设置了 LIUM_WORKSPACE / -w 时,lium init 会以状态码 2 退出:此时命令使用为该工作区保存的密钥,而 init 不会写入该密钥——请使用 lium keys create <name> --workspace <ws> --save。如果已导出 LIUM_API_KEY(或 LIUM_API_API_KEY),lium init 会跳过浏览器,设置 SSH 密钥,并说明密钥来自环境变量——SSH 路径会写入文件,但密钥不会;同时导出了密钥时,--api-key 会发出警告(JSON 中的 env_key)。 登录密钥可能过期或被撤销,因此,在已有保存的密钥时运行 lium init,会先通过 /users/me 验证该密钥。如果 API 拒绝该密钥(返回 401,或返回 403 并说明密钥所属的工作区已不存在或创建者已离开),就会按正常流程重新登录(Your saved API key has expired or was revoked. Starting a new login…);如果没有终端,则不会打开浏览器,且 lium init 会以退出码 6(saved_key_rejected)退出。对于其他 403(账号被封禁、出现防火墙页面)、429、5xx 或无响应,则会保留该密钥并显示警告。即使密钥仍然有效,lium init --force 也会重新登录;即使已有保存的密钥,lium init --session <ID> 也会兑换该会话。只有新登录成功生成密钥后,才会替换保存的密钥(配置文件会先写入临时文件,再重命名覆盖旧文件),因此,中止浏览器登录或会话未获批准都不会影响旧密钥。

首次使用时,会将 Pod 的 SSH 主机密钥固定保存在 ~/.lium/known_hosts/<pod-id> 下(适用于 lium ssh、lium up 以及 SDK 的 exec、stream_exec、rsync)。reboot、edit、switch_template 和 rm 会自行移除固定记录(容器及其密钥都会被替换)。 如果 Pod 之后提供了不同的密钥,系统会拒绝连接——SDK 会抛出 LiumHostKeyError,lium ssh 则会显示 OpenSSH 自带的“主机标识已更改”错误并停止——这可能是平台自行重启 Pod 后的情况,也可能意味着连接遭到拦截;如果 Pod 确实已重新配置,请删除该文件。指纹格式为 SHA256:…,与 ssh-keygen -lf 的输出一致。LIUM_SSH_INSECURE=1 可恢复旧版的接受任意密钥行为(每个被接受的密钥都会报告到 stderr)。lium ssh 使用由 Pod 的用户名、地址和端口构造的参数列表运行 OpenSSH;API 的连接字符串绝不会传给 shell。

脚本和 Agent(非交互式使用)

CLI 绝不会等待它无法显示的提示。当 stdin 不是终端,或设置了 LIUM_NONINTERACTIVE=1 时,本来需要提问的命令会采用文档规定的默认值,或立即失败(退出码 2),并提示应传入哪个标志:

export LIUM_API_KEY=...            # no browser login is attempted without a terminal
lium init --api-key $KEY           # or save the key once, without a browser
lium up --gpu H100 -y --no-ssh     # -y: rent without the confirmation prompt
lium rm my-pod -y                  # -y on every destructive command; a piped rm without it exits 2 and removes nothing
lium fund -w default -a 1.5 -y     # values that would be prompted for must be passed as options
面向 Agent 宿主的 MCP 服务

lium mcp 会通过 stdio 将 Lium 作为模型上下文协议服务提供,因此 Claude Desktop、Claude Code、Cursor 或任何 MCP 宿主都可以自行租用并使用 GPU。工具:list_gpus、rent_pod、list_pods、run_command、remove_pod、get_balance。该服务使用 lium init 保存的 API 密钥,或使用 LIUM_API_KEY。

pip install "lium.io[mcp]"
{"mcpServers": {"lium": {"command": "lium", "args": ["mcp"]}}}

无需安装任何内容,使用 uv 即可:

{"mcpServers": {"lium": {"command": "uvx", "args": ["--from", "lium.io[mcp]", "lium.io", "mcp"]}}}

rent_pod 设置 dry_run: true 时会先报价节点(层级、可靠性、每小时费用和账户余额),但不会租用;设置 enable_backups: false 则会租用 Pod,但不启用自动备份。租用的 Pod 会按秒计费,直到调用 remove_pod。托管式 MCP 服务 https://docs.lium.io/mcp(无需密钥,只读)是独立服务:它会搜索文档,并提供实时 GPU 价格和可用情况;rent_pod 使用其 search_gpus 返回的节点 ID。

崩溃报告(可选择启用,默认关闭)

除非你主动开启,否则 CLI 绝不会发送遥测数据:

lium config set telemetry.enabled true    # or: export LIUM_TELEMETRY=1
lium config set telemetry.enabled false   # off again

开启后,遇到意外错误(程序错误,显示为 Unexpected error: …)时,会报告一次异常信息、堆栈跟踪、命令名称(lium up)、CLI 版本、Python 版本、操作系统,以及 CLI 配置的 API 主机(lium.io 或你的 LIUM_BASE_URL)。API 错误、用法错误、参数、选项值和局部变量绝不会发送;异常消息中你在命令行传入的值(Pod 名称、路径)、主目录路径(macOS、Linux 和 Windows)、电子邮箱和 API 密钥都会被删除。报告会发送到 Lium 的 Sentry 项目;LIUM_SENTRY_DSN 可将报告发送到其他位置(例如自托管的 GlitchTip),而 LIUM_SENTRY_DSN=(空值)则会在启用报告的情况下仍将其关闭。如果值不是 DSN,程序会在 stderr 上显示一条警告,并关闭报告;命令本身仍会运行。

要求

  • Python 3.10 – 3.14(requires-python = ">=3.10, <3.15")
  • 链命令(lium provider …、lium fund)需要 provider extra——pip install 'lium.io[provider]'——其链库只能在 Python < 3.14 上构建;在 3.14 上,安装过程不会输出错误信息,运行 provider 命令时 CLI 会说明这一限制

开发

# Clone repository
git clone https://github.com/datura-ai/lium.git
cd lium

# Install in development mode
pip install -e .

此仓库是一个 uv 项目(uv.lock);CI 使用 uv sync --frozen --extra dev --extra provider 安装依赖, 并在 Python 3.10 和 3.12 上运行单元测试:

uv sync --frozen --extra dev --extra provider
uv run pytest test/ -q

.github/workflows/ci.yml(CI - Build Verification)会在每个 PR 上运行:单元测试、打包输入检查、 sdist/wheel 构建以及二进制目标矩阵检查(test/test_release_binary_targets.py)。二进制构建(在 Docker 中构建 Linux amd64/arm64,以及 macOS arm64)仅在打包输入发生变化时运行(pyproject.toml、 uv.lock、lium.spec、lium_entry.py、Dockerfile.build、scripts/install.sh、scripts/linux_bundle_report.py、 ci.yml、release.yml);PR 上不会构建 macOS Intel 版本。手动触发(gh workflow run ci.yml --ref <branch>) 会构建全部五个目标并运行实时 e2e(./e2e/run.sh,参见 e2e/README.md);否则,e2e 会按计划每天运行一次, 且不会在 PR 上运行。ci-ok(测试、打包、wheel 和目标矩阵作业的汇总)和 e2e-live 是 main 规则集要求的两个状态检查。

许可证

MIT 许可证——详情请参阅 LICENSE 文件。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。