Skip to main content

UIP Python SDK

Universal Inference Platform 的 Python 客户端库。

本文档与 uip_sdk/client.py 的 UIPClient 接口保持同步。所有公开方法、参数与返回类型均以源码为准。

安装

pip install uip-sdk

快速开始

from uip_sdk import UIPClient

# 方式 1: API Key
client = UIPClient(api_key="ggw-xxx...")

# 方式 2: JWT Token
client = UIPClient(token="eyJhbGciOiJIUzI1NiIs...")

# 方式 3: 环境变量 (UIP_API_KEY 或 UIP_TOKEN)
client = UIPClient()

# 指定 base_url / 超时 / 默认调度策略 / 传输层重试次数
# max_retries 默认 3,走 httpx transport 层(连接失败与瞬时错误自动重试)
client = UIPClient(
    base_url="http://10.0.1.115:51438",
    api_key="ggw-xxx...",
    timeout=300,
    strategy="least_queue",
)

# 作为上下文管理器使用(自动释放连接)
with UIPClient(api_key="ggw-xxx...") as client:
    print(client.chat(messages=[{"role": "user", "content": "你好"}]).text)

初始化参数:

参数 类型 默认值 说明
base_url str http://10.0.1.115:51438 UIP API 地址
api_key str | None None API Key(与 token 二选一)
token str | None None JWT Token(与 api_key 二选一)
timeout int 300 HTTP 超时秒数
strategy str | None None 默认调度策略
  • 三者皆为空时,自动读取环境变量 UIP_API_KEY / UIP_TOKEN;仍为空则抛出 AuthenticationError。
  • user_id / unit_id 为只读属性,构造时自动调用 /v1/users/me 解析。

推理

对话 (Chat Completions)

OpenAI 兼容接口。

resp = client.chat(
    messages=[{"role": "user", "content": "你好"}],
    model="qwen2.5:7b",
    temperature=0.7,
    max_tokens=512,
    top_p=1.0,
)
print(resp.text)              # 回复文本
print(resp.tokens.total)      # 总 token 数

流式:

for chunk in client.chat(messages=[...], model="qwen2.5:7b", stream=True):
    print(chunk.text, end="", flush=True)

流式生成 (Ollama 兼容)

for chunk in client.generate("写一首关于春天的诗", stream=True):
    print(chunk.text, end="", flush=True)

# 非流式
resp = client.generate("介绍一下你自己", model="qwen2.5:7b", system="你是助手")
print(resp.text)

参数:prompt、model、system、stream、options(Ollama 选项,如 {"num_predict": 100})。

嵌入向量

resp = client.embed(input="需要向量化的文本", model="bge-m3:567m")
print(len(resp.embedding))   # 768
print(resp.tokens.input)      # 输入 token 数

input 也支持 list[str](批量向量化)。

Rerank (文档重排序)

results = client.rerank(
    query="CBA季后赛战术分析",
    documents=["CBA联赛采用胜率决定排名", "篮球三分线距离为6.75米", "广东队采用全场紧逼战术"],
    model="Qwen3-Reranker-0.6B",
    top_n=2,
)
for r in results.results:
    print(f"#{r.index}: {r.document[:30]}... score={r.relevance_score:.2f}")

批量推理

batch = client.batch(prompts=["你好", "介绍你自己"], model="qwen2.5:7b")
for item in batch.results:
    print(f"[{item.index}] {item.response[:50]}")

文件上传

up = client.upload("/path/to/file.pdf")
print(up.filename, up.size, up.url, up.content_type)

模型列表

models = client.list_models()
for m in models:
    print(m.id, m.owned_by, m.modal_type)   # 模型 ID / 拥有方 / 模态类型

# modal_type 由 UIG /v1/models 直接返回,可按模态筛选
llm_models = [m for m in models if m.modal_type == "llm"]
# 另有 node_kind(local / remote)与 engine(umr / vllm / ollama)

对话会话(Chat Sessions)

UIP 侧 chat_sessions / chat_messages 表提供持久化对话能力。chat_in_session() 是推荐入口 —— 服务端 /v1/sessions/send 只存用户消息、不触发推理,完整一轮对话 需要 send → chat → save_response 三步,该方法把它们合成一次调用,并自动把会话历史 作为上下文带上。

sess = client.create_session(title="体测咨询", model="qwen2.5:7b")
sid = sess.id

# 一步完成:存用户消息 + 带历史上下文推理 + 存助手回复
resp = client.chat_in_session(sid, "什么是 BMI?")
print(resp.text)

# 流式同样支持,流结束后自动把完整回复落库
for chunk in client.chat_in_session(sid, "详细说说", stream=True):
    print(chunk.text, end="")

# 会话管理
sessions = client.list_sessions(limit=20)   # -> list[Session]
detail = client.get_session(sid)            # -> SessionDetail,含全部消息
client.update_session_title(sid, "新标题")
client.archive_session(sid)
client.delete_session(sid)

需要细粒度控制时可拆开用 send_message() / save_response()。

异步客户端(chat_in_session 按 stream 分别返回协程与 async generator):

resp = await client.chat_in_session(sid, "你好")

async for chunk in client.chat_in_session(sid, "你好", stream=True):
    print(chunk.text, end="")

非对话类单次推理(embedding / rerank / ocr)另有独立历史:

client.save_inference_history(modal_type="embedding", model_id="bge-m3:567m",
                              input_data={"text": "..."}, output_data={"dim": 1024})
history = client.get_inference_history(modal_type="embedding", limit=10)

指定调度策略

通过 with_strategy 链式设置本次请求的调度策略(写入请求头 X-UIP-Strategy),返回 self 可继续调用。

client.with_strategy("least_queue").generate("hi")

可选策略:model_first(按模型匹配)/ least_queue(最少队列优先)/ weighted_rr(加权轮询)/ affinity(亲和性复用)。

健康检查

print(client.ping())   # 返回服务状态 dict

UMR 通用推理(17 种模态全覆盖)

client.infer(model_id, payload) 是 UMR 统一运行时入口,一个接口覆盖全部 17 种 AI 模态。 model_id 采用 family:size 命名,payload 字段随模态不同;返回的 InferResponse.modal_type 为下表「模态类型」列的字符串值(与 umr/core/models.ModalType 枚举一致)。

# 模态类型 中文 代表模型 教育场景 SDK 调用
1 llm 大语言模型 Qwen2.5-7B 智能问答、作业辅导、行政助手 client.infer("qwen2.5:7b", {"prompt": ...})
2 asr 语音识别 Whisper-large-v3 外语语音评测、课堂录音转写 client.infer("whisper:large-v3", {"audio": ...})
3 tts 语音合成 SpeechT5 发音示范、无障碍朗读 client.infer("speecht5:base", {"text": ...})
4 vision 视觉理解 Qwen2.5-VL-7B 实验安全监控、实训操作评估 client.infer("qwen2.5-vl:7b", {"image": ...})
5 embedding 向量嵌入 BGE-M3 语义搜索、知识库检索、论文查重 client.infer("bge-m3:567m", {"text": ...})
6 rerank 重排序 BGE-Reranker 检索精排、RAG 精度提升 client.infer("bge-reranker:0.6b", {"query": ..., "documents": ...})
7 image_generation 图像生成 SDXL 教学素材创作、设计课程实训 client.infer("sdxl:base", {"prompt": ...})
8 object_detection 目标检测 YOLOv8 体育教学姿态分析、校园安防 client.infer("yolov8:m", {"image": ...})
9 segmentation 图像分割 SegFormer 医学影像教学、地理遥感实训 client.infer("segformer:b0", {"image": ...})
10 ocr 文字识别 PP-OCRv3 试卷批改、票据识别、古籍数字化 client.infer("pp-ocr:v3", {"image": ...})
11 video_understanding 视频理解 VideoMAE 体育动作分析、实验操作评估 client.infer("videomae:base", {"video": ...})
12 audio 音频处理 Wav2Vec2 音乐教学分析、声学实训 client.infer("wav2vec2:base", {"audio": ...})
13 gnn 图神经网络 GCN / GAT 知识图谱推理、课程推荐 client.infer("gcn:base", {"graph": ...})
14 encoder_only 编码器 BERT 文本分类、情感分析、命名实体识别 client.infer("bert:base", {"text": ...})
15 time_series 时间序列 Prophet 学生体能趋势预测、设备运维预警 client.infer("prophet:base", {"series": ...})
16 sci_compute 科学计算 ESM2 / T5 蛋白质结构预测、分子模拟 client.infer("esm2:base", {"sequence": ...})
17 ml 传统机器学习 XGBoost 数据挖掘教学、统计建模实训 client.infer("xgboost:base", {"features": ...})

注:Video 模态在 ModalType 中细分为 video_understanding(视频理解)与 video_generation(文生视频,如 Wan2.1),本表按论文口径统一归为第 11 项「视频理解」。其余枚举值(video、video_generation)调用方式相同,仅 modal_type 字符串不同。

逐模态调用示例:

from uip_sdk import UIPClient

client = UIPClient(api_key="ggw-xxx...")

# 1) 大语言模型 LLM — 智能问答
r = client.infer("qwen2.5:7b", {"prompt": "解释牛顿第二定律"})
print(r.modal_type, r.result)                       # llm / 回复文本

# 2) 语音识别 ASR — 课堂录音转写
r = client.infer("whisper:large-v3", {"audio": "lecture.wav"})
print(r.modal_type, r.result)                       # asr / 转写文本

# 3) 语音合成 TTS — 发音示范
r = client.infer("speecht5:base", {"text": "Hello, world", "speaker": 0})
print(r.modal_type, r.result)                       # tts / 音频 base64 或路径

# 4) 视觉理解 Vision — 实训操作评估
r = client.infer("qwen2.5-vl:7b", {"image": "lab.jpg", "prompt": "描述画面中的操作"})
print(r.modal_type, r.result)                       # vision / 描述文本

# 5) 向量嵌入 Embedding — 知识库检索
r = client.infer("bge-m3:567m", {"text": "GPU 显存调度"})
print(r.modal_type, len(r.result))                  # embedding / 向量维度(如 1024)

# 6) 重排序 Rerank — RAG 精排
r = client.infer("bge-reranker:0.6b",
                 {"query": "VAHS 是什么", "documents": ["显存感知调度", "天气报告"]})
print(r.modal_type, r.result)                       # rerank / 排序后文档列表

# 7) 图像生成 ImageGen — 教学素材
r = client.infer("sdxl:base", {"prompt": "a chemistry lab, flat illustration"})
print(r.modal_type, r.result)                       # image_generation / 图片 url 或 base64

# 8) 目标检测 ObjDetection — 体育姿态分析
r = client.infer("yolov8:m", {"image": "student.jpg"})
print(r.modal_type, r.result)                       # object_detection / 检测框列表

# 9) 图像分割 Segmentation — 医学影像
r = client.infer("segformer:b0", {"image": "xray.png"})
print(r.modal_type, r.result)                       # segmentation / mask 数据

# 10) 文字识别 OCR — 试卷批改
r = client.infer("pp-ocr:v3", {"image": "exam.png"})
print(r.modal_type, r.result)                       # ocr / 识别文本

# 11) 视频理解 Video — 动作分析
r = client.infer("videomae:base", {"video": "action.mp4"})
print(r.modal_type, r.result)                       # video_understanding / 标签或描述

# 12) 音频处理 Audio — 音乐分析
r = client.infer("wav2vec2:base", {"audio": "music.wav"})
print(r.modal_type, r.result)                       # audio / 特征或分类

# 13) 图神经网络 GNN — 课程推荐
r = client.infer("gcn:base", {"graph": {"nodes": [...], "edges": [...]}})
print(r.modal_type, r.result)                       # gnn / 节点表示或预测

# 14) 编码器 EncoderOnly — 情感分析
r = client.infer("bert:base", {"text": "这部电影太精彩了"})
print(r.modal_type, r.result)                       # encoder_only / 向量或分类

# 15) 时间序列 TimeSeries — 体能趋势预测
r = client.infer("prophet:base", {"series": [120, 128, 131, 135], "periods": 3})
print(r.modal_type, r.result)                       # time_series / 预测值

# 16) 科学计算 SciCompute — 蛋白质结构
r = client.infer("esm2:base", {"sequence": "MKTAYIAKQR..."})
print(r.modal_type, r.result)                       # sci_compute / 结构或表示

# 17) 传统机器学习 ML — 统计建模
r = client.infer("xgboost:base", {"features": [0.1, 2.3, 5.0]})
print(r.modal_type, r.result)                       # ml / 预测值

说明:payload 字段取决于具体模型适配器实现,上例为典型用法;所有 InferResponse 均带 raw 字段可读取原始返回。modal_type 由 UMR 适配器自动回写,可用于按模态做路由、计费与历史过滤(如 get_inference_history(modal_type="llm"))。

联邦推理

UIP→UIF→UIS→UIG 跨机构推理链路,需方通过 SDK 向供方发起推理请求。

# 自动选择最优供方
result = client.federated_infer(
    model_id="qwen2.5:7b",
    payload={"prompt": "介绍中国体育教育发展"},
)
print(result.supplier_unit)    # 供方单位 ID
print(result.supplier_node)    # 供方 GPU 节点名
print(result.cost_rmb)         # 人民币费用
print(result.cost_credits)     # 积分费用

# 指定供方 + GPU 类型偏好 + 双重价格上限
result = client.federated_infer(
    model_id="qwen2.5:7b",
    payload={"prompt": "你好"},
    target_unit="tsinghua-sports",    # 指定供方单位
    prefer_gpu_type="rtx_5090",       # GPU 类型偏好
    max_price_rmb=1.0,                # 人民币价格上限
    max_price_credits=10.0,           # 积分价格上限
)

训练管理

# 提交训练任务(含 gpu_type 和 unit_id 多租户隔离)
job = client.submit_job(
    model="qwen2.5:7b",
    name="fine-tune-v1",
    framework="transformers",     # 训练框架
    dataset="my-data",            # 数据集名
    script="train.py",            # 训练脚本(可选)
    n_gpus=1,
    epochs=3,
    learning_rate=1e-5,
    batch_size=4,
    priority=0,
    timeout=3600,
    gpu_type="rtx_5090",          # GPU 类型追踪
    unit_id="tsinghua-sports",    # 多租户命名空间隔离
)
print(job["job_id"])

### 训练配方(推荐使用)

训练模板的正确形态是**结构化配方**而非源码文本。一个 recipe 同时确定
`framework` + `task_type` + 一组经过验证的默认超参,调用方只给 `model` / `dataset`
即可开跑,无需理解 DeepSpeed ZeRO 之类的框架细节
(对标 OpenAI `hyperparameters`、Vertex AI trainer 类、HF TRL `SFTConfig`)。

```python
# 查看全部配方
for r in client.list_recipes():
    print(r.name, "->", r.framework, r.task_type, "lr=", r.learning_rate)

# 用配方提交:一行开跑 LoRA 微调
job = client.submit_job(model="qwen2.5:0.5b", dataset="my-sft", recipe="lora_sft")

# 显式传入的参数优先于配方默认值
job = client.submit_job(model="qwen2.5:0.5b", dataset="my-sft",
                        recipe="lora_sft", epochs=10, learning_rate=5e-5)
recipe framework task_type 默认 lr batch max_len 适用
sft transformers sft 1e-5 4 512 通用全参数监督微调(默认)
lora_sft unsloth sft 2e-4 4 1024 LoRA 低秩微调,单卡 8~24GB 首选
qlora_sft unsloth sft 1e-4 2 1024 4bit 量化 LoRA,显存最省
deepspeed_sft deepspeed sft 1e-5 8 1024 多卡分布式全参微调
llama_factory_sft llama-factory sft 1e-5 4 512 LLaMA-Factory 生态
axolotl_sft axolotl sft 1e-5 4 512 Axolotl 配置驱动
torchtune_sft torchtune sft 2e-5 4 512 PyTorch 官方 torchtune
text_classification transformers text_classification 2e-5 16 128 文本分类
image_classification transformers image_classification 5e-5 16 64 图像分类
audio_classification transformers audio_classification 5e-5 8 64 音频分类

提交前先校验参数,避免无效任务占用 GPU 队列:

v = client.validate_job(model="qwen2.5:0.5b", dataset="demo", recipe="lora_sft")
print(v.valid)      # 是否通过
print(v.errors)     # 硬错误(会阻断提交)
print(v.warnings)   # 软警告

支持的 8 种训练框架

submit_job(framework=...) 的 framework 对应 UMT 的模板文件 <framework>.py.j2,共支持 8 种训练环境。传入未匹配的框架名时,UMT 自动回退到 transformers 模板。

# framework 值 模板文件 适用场景
1 transformers transformers.py.j2 HuggingFace Transformers / PyTorch 原生,标准 SFT、预训练
2 deepspeed deepspeed.py.j2 DeepSpeed 分布式训练,多卡大模型训练
3 llama-factory llama-factory.py.j2 LLaMA-Factory 低代码微调框架
4 axolotl axolotl.py.j2 Axolotl 指令 / 多模态微调
5 unsloth unsloth.py.j2 Unsloth 量化高效微调(低显存)
6 torchtune torchtune.py.j2 PyTorch 官方 recipes(TorchTune)
7 swift UIP 内联模板 魔搭 ModelScope 官方 LLM 微调框架,支持 200+ 模型
8 custom custom.py.j2 完全自定义训练模板,由 script 指定入口

framework 与 task_type 是两个维度:上表 8 项是训练框架; task_type(sft / text_classification / image_classification / audio_classification)是独立的任务类型维度。UMT 的 templates/ 目录里 除框架模板外还有 image_classification.py.j2 / text_classification.py.j2 / audio_classification.py.j2 三个任务模板 —— 它们按 task_type 选取,不是 framework。 推荐直接用 recipe= 配方,避免手工拼装这两个维度。

逐框架提交示例:

# 1) HuggingFace Transformers / PyTorch 原生
job = client.submit_job(model="qwen2.5:7b", name="sft-v1", framework="transformers",
                        dataset="my-sft", epochs=3, learning_rate=1e-5, batch_size=4)

# 2) DeepSpeed 分布式训练(多卡)
job = client.submit_job(model="qwen2.5:14b", name="ds-v1", framework="deepspeed",
                        dataset="my-sft", n_gpus=4, gpu_type="rtx_5090")

# 3) LLaMA-Factory 微调
job = client.submit_job(model="llama3:8b", name="lf-v1", framework="llama-factory",
                        dataset="my-sft", batch_size=8)

# 4) Axolotl 指令微调
job = client.submit_job(model="qwen2.5:7b", name="axolotl-v1", framework="axolotl",
                        dataset="instruct-en", batch_size=2)

# 5) Unsloth 量化高效微调(低显存)
job = client.submit_job(model="qwen2.5:7b", name="unsloth-v1", framework="unsloth",
                        dataset="my-sft", n_gpus=1, gpu_type="rtx_4070")

# 6) TorchTune
job = client.submit_job(model="llama3:8b", name="tt-v1", framework="torchtune",
                        dataset="my-sft", epochs=1)

# 7) 通用 PyTorch 训练脚本
job = client.submit_job(model="resnet50", name="train-v1", framework="train",
                        dataset="imagenet-mini", script="train.py", n_gpus=2)

# 8) 自定义模板
job = client.submit_job(model="custom-model", name="custom-v1", framework="custom",
                        dataset="my-data", script="my_train.py", unit_id="tsinghua-sports")

提示:可用 client.list_templates() 查看服务端实际支持的框架模板清单,并用 client.get_template(framework="deepspeed") 拉取对应训练脚本模板源码;框架特有的超参(如 DeepSpeed 的 ZeRO 配置、Unsloth 的 4bit 量化)通过在 dataset/script 或模板内指定,而非 submit_job 的顶层参数。

任务列表 / 详情 / 取消

jobs = client.list_jobs(status="running", limit=50) detail = client.get_job("job-xxx") client.cancel_job("job-xxx")

训练日志(长轮询 / SSE 流式)

logs = client.get_job_logs("job-xxx", tail=50) for line in client.stream_job_logs("job-xxx"): print(line, end="")

断点 / 指标

ckpts = client.list_checkpoints("job-xxx") latest = client.get_latest_checkpoint("job-xxx") metrics = client.get_training_metrics("job-xxx")


### 数据集与模板

```python
# 数据集列表
datasets = client.list_datasets()
for d in datasets.get("datasets", []):
    print(d["name"], d["size"])

# 上传数据集(base64 内联,支持多租户隔离)
client.upload_dataset(name="my-data", file_path="/path/to/data.jsonl", unit_id="tsinghua-sports")

# 预览数据集前 N 行
preview = client.preview_dataset(name="my-data", lines=20)

# 训练配方(推荐:结构化训练模板)
for r in client.list_recipes():
    print(r.name, "->", r.framework, r.task_type)

# 框架模板源码(escape hatch:仅供需要改写训练脚本本体的高级场景)
templates = client.list_templates()               # -> list[TemplateItem]
tpl = client.get_template(framework="transformers")  # -> TemplateItem
print(tpl.name, tpl.description)
print(tpl.code)   # 源码改完以 submit_job(script=...) 提交

GPU 资源与模型部署

训练完成后把检查点部署为可推理模型,打通「训练 → 推理」闭环:

# GPU 资源总览(逐卡显存 / 利用率 / 状态,提交训练前先看资源)
overview = client.gpu_overview()

# 查看某作业的检查点,挑一个 step 部署
ckpts = client.list_checkpoints("job-xxx")
step = ckpts[-1].step

# 部署为可推理模型:导出 LoRA → 分发推理主机 → 验证推理 → 登记
client.register_model(job_id="job-xxx", checkpoint_step=step,
                      prompt="介绍一下人工智能")

# 已部署模型列表(可按作业 ID 过滤)
deployments = client.list_deployments(job_id="job-xxx")

# 下载检查点权重(zip 二进制)
data = client.download_checkpoint("job-xxx", step)
open("ckpt.zip", "wb").write(data)

# UMR 注册表(经 UIF 联邦路由获取已注册模型 / 能力)
registry = client.umr_registry()

# 当前登录用户信息
me = client.get_me()

计费与余额

from uip_sdk import BalanceResponse

# 查询余额(双轨:人民币 + 积分)
bal: BalanceResponse = client.get_balance()
print(f"人民币: ¥{bal.balance_rmb:.2f}")
print(f"积分:   {bal.balance_credits:.0f} credits")
print(f"冻结:   ¥{bal.frozen_rmb:.2f} / {bal.frozen_credits:.0f} credits")

# 快速查询积分
credits = client.get_credits()

# 交易记录(支持币种 / 类型过滤,分页)
txns = client.get_transactions(page=1, page_size=20, currency="credits", tx_type="consume")
for item in txns.items:
    print(f"{item.created_at} {item.tx_type}: {item.amount} {item.currency} — {item.description}")

# 管理员充值(需 admin 权限)
resp = client.recharge(user_id=42, amount=100.0, currency="credits", description="赠送积分")
print(f"充值成功: tx_id={resp.tx_id}, balance_after={resp.balance_after}")

历史与 QoS

# QoS 信息(限流/配额状态)
qos = client.get_qos()
print(qos)

# 推理历史(按模态过滤,默认 llm)
history = client.get_inference_history(modal_type="llm", limit=30)
for h in history.get("items", []):
    print(h)

# 删除某条推理历史
client.delete_inference_history(history_id=123)

返回对象字段速查

所有响应对象均带 raw 字段(原始响应 dict)以便扩展读取。

返回类型 主要字段
ChatResponse text, model, tokens(input/output/total), finish_reason, raw
GenResponse text, thinking, model, done, done_reason, tokens, elapsed_ms, raw
StreamChunk text, done, eval_count, tokens, index
EmbedResponse embedding: list[float], model, tokens, raw
RerankResponse results[RerankItem(index,document,relevance_score)], total, model, elapsed_ms, raw
BatchResponse total, completed, errors, elapsed_ms, results[BatchResult(index,prompt,response,error)], model, raw
UploadResponse filename, original_name, size, url, content_type, raw
ModelItem id, created, owned_by
InferResponse result, model_id, modal_type, raw
FederatedInferResponse result, model_id, supplier_unit, supplier_node, modal_type, tokens, cost_rmb, cost_credits, elapsed_ms, raw
TrainingJob job_id, name, model, framework, dataset, status, hostname, gpu_ids, gpu_type, unit_id, created_at, priority, logs
Checkpoint job_id, epoch, step, metrics, saved_at
TrainMetrics job_id, metrics, checkpoints
DatasetItem name, path, size
TemplateItem framework, name, description, code
BalanceResponse user_id, username, balance_rmb, balance_credits, frozen_rmb, frozen_credits, raw
TransactionItem tx_id, amount, currency, tx_type, description, balance_after, created_at
TransactionResponse total, page, page_size, items, raw
RechargeResponse success, tx_id, amount, currency, balance_after, message, raw

异常处理

所有异常继承自 UIPError,捕获基类即可统一处理。

异常 HTTP 含义
AuthenticationError 401 认证失败
InsufficientBalanceError 402 余额不足
NotFoundError 404 资源不存在
RateLimitError 429 请求频率受限
UIGOfflineError 503 UIG 全部离线
TimeoutError 504 请求超时
ServerError 5xx 服务端错误
UIPError — 基础异常(其他)
from uip_sdk import UIPClient
from uip_sdk.errors import UIPError, InsufficientBalanceError

try:
    client.generate("hi")
except InsufficientBalanceError as e:
    print("余额不足:", e)
except UIPError as e:
    print("请求失败:", e.status_code, e.detail)

注:UIPError / AuthenticationError / InsufficientBalanceError / UIGOfflineError / TimeoutError / RateLimitError 已在 uip_sdk 顶层直接导出;NotFoundError / ServerError 可通过 from uip_sdk.errors import NotFoundError, ServerError 使用。

资源释放

client.close()   # 关闭底层 httpx 连接

# 或使用 with 上下文管理器(推荐)
with UIPClient(api_key="...") as client:
    ...

License

Apache License 2.0. Copyright (c) 2026 Zhu Wenbo (zwb.2002@tsinghua.org.cn).

UMRClient — 引擎层直连

UIPClient 走平台(认证/计费/审计);UMRClient 直连 UMR 引擎(59:51450),覆盖引擎级管理(load/unload/vram/registry/部署注册)与全部 20 个 UMR 端点。

from uip_sdk import UMRClient

# X-API-Key 认证 (UIR_INTERNAL_KEY)
umr = UMRClient(base_url="http://10.0.1.59:51450", api_key="<internal-key>")

# 引擎级管理
umr.list_models()          # by_modal 模型清单
umr.vram_status()          # 显存状态
umr.registry_status()      # 注册表状态
umr.load_model("qwen2.5:7b") / umr.unload_model("qwen2.5:7b")
umr.register_model(model_id="deploy-xxx", base_model="/path/to/base",
                   adapter_path="/path/to/lora")   # 部署 LoRA 注册

# 引擎级推理
umr.infer("qwen2.5:7b", {"messages": [{"role": "user", "content": "hi"}]})
umr.chat_completions({"model": "qwen2.5:7b", "messages": [...]})  # OpenAI 兼容

OAuth2 应用与 SSO(AI 实训室等应用接入)

UIP 作为平台底座为应用(如 AI 实训室)提供 OAuth2 授权码登录与应用级 JWT:

from uip_sdk import UIPClient, exchange_oauth_token

client = UIPClient(base_url="http://10.0.1.115:51438", api_key="<your-api-key>")

# 1. 注册应用(client_secret 仅此一次可见,妥善保存)
app = client.oauth_create_app(
    name="AI 实训室",
    scope="lab inference training",
    redirect_uris="http://<ai-lab-host>/callback",
)
cid, secret = app["client_id"], app["client_secret"]

# 2. 用户已登录时签发一次性授权码(10min)
auth = client.oauth_authorize(client_id=cid, scope="lab inference")
code = auth["code"]

# 3. 授权码换应用级 JWT(实训室后端主入口)
tok = client.oauth_exchange_token(code=code, client_id=cid, client_secret=secret)
# 等价便捷函数(无需 UIPClient 实例):
# tok = exchange_oauth_token(base_url="http://10.0.1.115:51438", code=code,
#                            client_id=cid, client_secret=secret)

# 4. 应用管理
client.oauth_list_apps()
client.oauth_revoke_app(client_id=cid)

返回的 JWT 携带 scope(权限范围)与 azp(来源应用),实训室据此代表用户在 UIP 侧访问资源。

异步客户端(与同步客户端方法级对齐)

AsyncUIPClient 与 UIPClient 方法级完全对齐(零缺口):会话、训练、 模板、数据集、计费、OAuth、文件上传全部可用。

from uip_sdk import AsyncUIPClient

async with AsyncUIPClient(api_key="ggw-xxx") as client:
    sess = await client.create_session(model="qwen2.5:7b")
    resp = await client.chat_in_session(sess.id, "你好")
    jobs = await client.list_jobs(status="running")   # -> list[TrainingJob]
    ckpt = await client.get_latest_checkpoint(jobs[0].job_id)  # -> Checkpoint | None

关于返回类型:绝大多数方法返回 dataclass,且每个 dataclass 都带 raw 字段保留服务端原始响应 —— 服务端后续新增字段也不会丢信息。少数方法仍返回 裸 dict:get_job_logs / get_qos / preview_dataset / send_message / submit_job / ping / OAuth 系列,因为它们的返回结构随模型或端点而异, 强类型化反而会造成字段丢失。

chat_in_session 在 async 下是普通 def(非 async def),按 stream 分别返回协程与 async generator:

resp = await client.chat_in_session(sid, "你好")

async for chunk in client.chat_in_session(sid, "你好", stream=True):
    print(chunk.text, end="")

异步流式(FastAPI 后端推荐)

实训室等 async 后端集成推理工作台流式时,使用 AsyncUIPClient(对标 openai-python 的 AsyncOpenAI 模式),不占线程、不阻塞事件循环:

from uip_sdk import AsyncUIPClient

async with AsyncUIPClient(base_url="http://10.0.1.115:51438", api_key="<your-api-key>") as client:
    # 流式:打字机效果
    async for chunk in client.chat_stream([{"role": "user", "content": "你好"}]):
        print(chunk.text, end="", flush=True)

    # 非流式
    resp = await client.chat([{"role": "user", "content": "hi"}])
    print(resp.text)

    # Ollama 兼容 generate 流式
    async for chunk in client.generate_stream("你好"):
        print(chunk.text, end="", flush=True)

    # embedding
    emb = await client.embed("AI 实训室")
    print(emb.dimensions)

流式链路:实训室 FastAPI -> UIP 网关(SSE 透传) -> UIG -> UMR,SDK async 边收边出。

Metadata

Release files for uip-sdk 0.18.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for uip-sdk 0.18.0
File Size Uploaded Provenance
uip_sdk-0.18.0.tar.gz 69.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for uip-sdk 0.18.0
File Interpreter ABI Platform
uip_sdk-0.18.0-py3-none-any.whl Python 3 none any Details

Total release size: 119.6 kB

Release files / uip_sdk-0.18.0.tar.gz

Download URL uip_sdk-0.18.0.tar.gz
Size 69.1 kB
Tags Source
SHA-256 checksum
How to use checksums
8cecfda33436a576f159e368f1b062c9a58db3aaba03c9d96c6681ed24b04be0
BLAKE2b-256 checksum
How to use checksums
5fcade214667efd0afa1de93f3420fcb7e0e67845758a1e3653f9539d34e6b5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / uip_sdk-0.18.0-py3-none-any.whl

Download URL uip_sdk-0.18.0-py3-none-any.whl
Size 50.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b996c9dda010c9755dca920781fd4af43106d98ecfdf11bf0d433db192faeec9
BLAKE2b-256 checksum
How to use checksums
d0d0d5ccf369dbe03b6a6bbccab2f5d26547890b9de558e33276872ca9708524
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for uip-sdk 0.18.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.18.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page