关于 Lium GPU Cloud
Lium 提供命令行工具和 Python SDK,用于在 Lium 平台租用及管理 GPU pod。它支持单 pod 任务和多节点集群,可执行命令、运行后台任务并移除资源。
主要功能
- 01租用和移除 GPU pod
- 02执行命令并查看 GPU 状态
- 03将 Python 函数交由 pod 运行
- 04运行后台任务并重新连接
- 05创建多节点集群
适用场景
- 01运行 GPU 推理或训练
- 02通过脚本自动管理 pod 生命周期
- 03在多个 GPU 节点上运行分布式任务
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
6收录的工具列表 · 更新于 今天
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| limit | integer | 否 | |
| gpu_type | any | 否 | |
| gpu_count | any | 否 |
详细介绍
Lium — Python SDK 和 CLI
lium.io 是一个 Python 包,提供命令行界面和 Python SDK,用于管理 Lium 平台上的 GPU Pod。安装一次,即可根据任务选择合适的界面。
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。
文档
- **CLI 文档:**https://docs.lium.io/developers/cli/overview
- **SDK 文档:**https://docs.lium.io/developers/sdk
- 退出代码和 JSON 错误信封:docs/exit-codes.md — 命令失败时脚本或 Agent 会收到什么(
--format json、LIUM_OUTPUT=json)。 - Agent 和脚本:docs/agents.md — 端到端的非交互式流程(环境变量认证、JSON 输出、退出代码、
up → exec → rsync → rm、Pod 注意事项)。
二进制版本
- 支持的二进制目标:
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 连接到 Podlium 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 复制到另一个 Podlium rm <POD>- 删除/停止 Pod(在脚本中添加--name-only可拒绝lium ps行号;--format json会输出已删除的内容及其预估支出;--rating 1-5 --feedback "..."可在同一次调用中为节点评分)lium reboot <POD>- 重启 Podlium 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-unbudgetedlium 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 JWTlium 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>- 查看当前租用该节点的 Podlium 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_name | 8×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_source | measured(已检查或取平均值)或 reported(单次测速样本,即表格中的 ~);没有数据时为 null |
available_ports | 可用于 --ports 的空闲端口 |
docker_in_docker | sysbox 运行时,即可在 pod 内使用 docker run |
is_pareto | ★ 标记 |
max_cuda_version | 驱动支持的最高 CUDA 版本 |
tier | secure 或 spot(可回收) |
link, nvlink, p2p | Link 列(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 负载。
功能
- 双重接口:同一个包同时提供
liumCLI 和 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)需要providerextra——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 文件。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。