| name | taiji-model-deploy |
| description | 在太极平台部署 / 关闭 / 调用混元模型在线推理服务。当用户说"部署 <模型名>""把 xxx 模型部署起来""关掉 <服务>""缩容到 0""这个服务怎么请求""测一下服务通不通"时使用。覆盖三件事:克隆式部署(含必须补建服务组这一坑)、缩容释放 GPU、OpenAI 兼容的最小调用示例。 |
太极模型部署 / 关闭 / 调用
三个动作,各自最短链路。所有平台操作走 taiji MCP(connect_mcp.py),模型调用走内网 stream-server 端点。
本 skill 的辅助脚本在 scripts/(下文写作 <skill-dir>/scripts/...,<skill-dir> = 本 SKILL.md 所在目录)。
依赖:太极 MCP skill(taiji-basic-platform-skills)已安装且 PAT token 已配置;调用侧只需 requests。
凭证配置
调用侧(C 段)需要内网 stream-server 的 Bearer token,走环境变量,不写进代码:
export TAIJI_STREAM_TOKEN=<token>
平台侧(A/B 段)的太极 PAT token 由 taiji-basic-platform-skills 自己管理(~/.config/taiji/credentials.json),本 skill 不重复处理。
何时用
- 部署:「部署 hy3.1_a3b_xxx_step240」「把这几个 ckpt 都起起来,每个 2 实例」
- 关闭:「关掉那几个服务」「缩容到 0」「释放 GPU」
- 调用:「服务怎么请求」「测一下通不通」「跑个推理」
前置常量(按需向用户确认)
| 项 | 默认值 | 说明 |
|---|
WSID | 10103 | 工作空间 ID |
APP_GROUP | TaiJi_HYAide_PosttrainINF_NJ_H20 | 应用组,决定卡型/地域可选范围 |
LOCATION | zw | 部署地域,须与模型 location_infos 有交集 |
GPU | H20 | 卡型 |
REPLICAS | 用户指定 | 实例数;单实例卡数由模板决定(A3B/A20B 都是 8) |
MCP 指向 service-deploy 子 skill 的客户端:
MCP=/root/.tclaude/skills/taiji-basic-platform-skills/sub-skills/service-deploy-skill/scripts/connect_mcp.py
MCP_MODEL=/root/.tclaude/skills/taiji-basic-platform-skills/sub-skills/model-manage-skill/scripts/connect_mcp.py
MCP_RES=/root/.tclaude/skills/taiji-basic-platform-skills/sub-skills/resource-mgmt-skill/scripts/connect_mcp.py
新网关所有响应都包在 {"code":0,"message":"success","data":{...}} 里,业务字段在 data 层。解析时务必先取 data。
A. 部署
步骤 1 — 查模型卡拿 model_id
python3 $MCP_MODEL call search_hunyuan_models_cards '{"wsid": 10103, "keyword": "<模型名或前缀>"}'
取返回 data.items[].model_id(字段名是 model_id,不是 mould_id)。搜不到就换更短的关键词。
步骤 2 — 确认模型地域
python3 $MCP_MODEL call get_hunyuan_models_card_detail '{"model_id": <ID>, "wsid": 10103}'
看 data.location_infos[].location,必须包含目标 LOCATION,否则跨地域拉取会慢到数小时。同时记下 scene_type(text → service_scene=text_to_text)。
步骤 3 — 查配额(决定卡型,也用于判断能否扩到目标实例数)
python3 $MCP_RES call query_shared_resources_gpu_info_batch '{"app_group_ids": ["TaiJi_HYAide_PosttrainINF_NJ_H20"]}'
data[].noraml[](注意后端把 normal 拼错成 noraml):按 (card_type, location) 给 total/used/available。
data[].personal_normal[]:个人配额池。这一项 available=0 时,即使应用组还有几百卡空余,扩容单也只会停在 status=ready 排队 —— 这是最容易误判成"部署失败"的情况。
步骤 4 — 找骨架服务
克隆需要一个已有服务当骨架(其 GPU/地域/应用组会被模板和显式参数覆盖,所以骨架选同系列任意一个即可):
python3 $MCP call list_deploy_inferences '{"wsid": 10103, "keyword": "<同系列关键词>", "page": 1, "page_size": 20}'
用返回的 name(短名),不要用 service(带 _AIDE 后缀,会报 400)。
步骤 5 — 执行部署
用本 skill 的 scripts/deploy_from_template.py(在官方脚本基础上修了新网关响应解包,官方版会把有模板的模型误判成"无推理模板"):
python3 <skill-dir>/scripts/deploy_from_template.py \
--model-id <ID> --gpu-name H20 --service-scene text_to_text \
--skeleton "<骨架服务 name>" --new-name "<新服务名>" \
--wsid 10103 --app-group-id "TaiJi_HYAide_PosttrainINF_NJ_H20" \
--location zw --model-location zw
脚本内部 = get_deploy_template_detail(拿镜像/TP/PP/envs/启动命令)→ clone_deploy_inference。输出 ✅ service_id=...。
service_id=None 是正常的,clone 的返回也被网关包了一层,脚本读不到 id 而已,服务已建好 —— 用步骤 7 核实,别重复部署。
步骤 6 — 🔴 补建服务组(最容易漏,漏了服务完全不可用)
clone_deploy_inference 的 auto_create_service 默认 false,克隆出的服务没有同名服务组。此时实例能正常 Running,但 openapi 路由查不到模型,调用直接报:
{'code': 'model info not found or no available instances', 'ret_code': -2002, 'type': 'ModelRouteError'}
每个新服务都要补一张同名服务组:
python3 $MCP call create_deploy_service '{"service_name": "<服务名>", "wsid": 10103,
"desc": "<服务名>", "inference_names": ["<服务名>"],
"weight": [{"name": "H20", "weight": 10}]}'
步骤 7 — 扩容到目标实例数并核实
clone 默认起 1 个实例,要 N 个就发扩容单:
python3 <skill-dir>/scripts/scale.py --replicas <N> <服务名或ID> ...
- 底层是
create_deploy_inference_change;change_type 不用传,后端按传了 replicas 自动推断为 scale。
- 返回
status=ready 表示已受理在排队;old_replicas -> new_replicas 可核对。
- 报「同一个服务不能同时发起两个扩缩容变更任务」= 上一单还挂着,等它,不要重复发。
- 单子长期停在 ready 且实例不涨 → 回步骤 3 看个人配额池,多半是配额满了在排队,不是配置错误。
核实状态:
python3 <skill-dir>/scripts/check_status.py <服务名1> <服务名2> ...
输出 pods / 目标实例 / Running / 状态表格。pods=N/N 且 status1=服务中 才算就绪。
步骤 8 — 探活
平台显示 Running 之后,路由仍可能要一两分钟才生效。用真实请求探活,别只看 pods:
python3 <skill-dir>/scripts/probe.py <服务名>
exit 0 = 可用。首次探活失败先重试几次;持续报 -2002 就回步骤 6 查服务组是否漏建。
B. 关闭(缩容到 0)
默认用缩容而不是删除:服务定义和服务组保留,下次复跑只需再发一张扩容单,不用重新部署;GPU 立即释放。
python3 <skill-dir>/scripts/scale.py --replicas 0 <服务名或ID> ...
再用 check_status.py 核实,目标是 pods=0/0 / 无实例。
缩容属于影响线上服务的写操作 —— 执行前复述一遍要关哪几个服务给用户确认,除非用户已明确说"直接关"。
真要彻底删除服务/服务组请去 Web 界面,MCP 未暴露删除接口。
C. 调用(minimal example)
可直接跑脚本,也可把 scripts/call_example.py 的 chat() 拷进自己代码:
python3 <skill-dir>/scripts/call_example.py <服务名> "你的问题"
python3 <skill-dir>/scripts/call_example.py <服务名> "..." --model-type A20B --temperature 0
内网 OpenAI 兼容端点,认证靠固定 Bearer token + Wsid header:
import json, os, uuid, requests
URL = "http://stream-server-online-openapi.turbotke.production.polaris:1081/openapi/chat/completions"
HEADERS = {
"Content-Type": "application/json",
"Authorization": f"Bearer {os.environ['TAIJI_STREAM_TOKEN']}",
"Wsid": "10103",
}
payload = {
"model": "<服务名>",
"messages": [
{"role": "system", "content": ""},
{"role": "user", "content": "你好"},
],
"temperature": 0.9,
"top_p": 1.0,
"top_k": -1,
"repetition_penalty": 1.0,
"output_seq_len": 131072,
"max_input_seq_len": 131072,
"stream": True,
"openai_infer": True,
"chat_template_kwargs": {"reasoning_effort": "high"},
"system_prompt": "",
"query_id": f"probe_{uuid.uuid4()}",
}
resp = requests.post(URL, headers=HEADERS, json=payload, stream=, timeout=)
content, reasoning, finish = [], [],
raw resp.iter_lines(decode_unicode=):
line = (raw ).strip()
line line.startswith():
line.startswith():
line = line[:].strip()
line line == :
data = json.loads(line)
data:
RuntimeError(data[])
ch data.get() []:
ch.get():
finish = ch[]
blk = ch.get() ch.get() {}
blk.get():
content.append((blk[]))
blk.get():
reasoning.append((blk[]))
(, finish)
(, .join(reasoning)[:])
(, .join(content)[:])
要点:
model 传服务名(部署时的 --new-name),不是模型卡名。端点不校验模型名,任意已部署服务名直接透传。
query_id 必填且每次唯一,否则可能被去重/拒绝。
- A3B vs A20B 采样参数不同:A20B 额外带
chat_template_kwargs.interleaved_thinking=True。两者都 temperature=0.9 / top_p=1.0 / top_k=-1 / max_tokens=131072。judge 类用途要显式设 temperature=0。
reasoning_content 要单独收:思考内容走这个字段,正文走 content。thinking 模型可能把内容全写在 reasoning 里而 content 只剩一句话 —— 判断输出是否为空要看 content。
- 端点有间歇性
ConnectionResetError(104) / first char timeout,必须带重试。
- 另有 offline 端点
http://stream-server-offline-sbs-pince-10103.turbotke.production.polaris:81/openapi/chat/completions,同样的 payload。
排障速查
| 现象 | 原因 | 处理 |
|---|
-2002 model info not found 但 pods 正常 | 没建服务组 | 部署步骤 6 |
无推理模板(image_name 为空) | 官方脚本没解包 data 层 | 用本 skill 的 deploy_from_template.py |
扩容单 status=ready 但实例不涨 | 个人配额池满 | 步骤 3 看 personal_normal.available,等释放 |
| 「不能同时发起两个扩缩容变更任务」 | 前一单未结束 | 等,别重发 |
AuthorizationError / forbidden request for Authorization[Bearer ...] | TAIJI_STREAM_TOKEN 未设或 Wsid header 缺失 | 检查环境变量与 headers |
clone 返回 service_id=None | 网关包装,非失败 | 用 check_status.py 核实 |
| 部署后立刻探活失败 | 路由生效有延迟 | 重试几次再判断 |
批量部署
多个 ckpt 一起部署时,按 步骤 5 → 6 → 7 逐个服务走完,不要把 clone 全发完再统一补服务组 —— 漏一个就会出现"实例在跑但请求不通"且不易察觉。最后统一用 check_status.py 过一遍。