Skip to content

Commit 1870500

Browse files
committed
feat: code review fixture
1 parent 19b7aac commit 1870500

17 files changed

Lines changed: 217 additions & 117 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Equip your AI Agent out-of-the-box with these capabilities, composable across co
3838
- **MCP integration** — Orchestrate Bailian MCP servers: list services, inspect tools, and invoke any tool directly from the terminal
3939
- **Web search** — Real-time internet retrieval for up-to-date, accurate answers
4040
- **Model recommendation** — Describe your scenario and get best-fit model suggestions; supports scoped search, model comparison, and alternative discovery
41-
- **Fine-tuning & deployment** — Upload datasets, create SFT/LoRA/DPO/CPT jobs (`finetune create`), probe job status non-blockingly (`finetune watch`), query per-model training capability (`finetune capability`), and deploy trained models as endpoints (`deploy create`)
41+
- **Fine-tuning & deployment** — Upload datasets, create text/audio/image fine-tune jobs (`finetune text|audio|image create`; text covers SFT/LoRA/DPO/CPT), probe job status non-blockingly (`finetune watch`), query per-model training capability (`finetune capability`), and deploy trained models as endpoints (`deploy text|audio|image create`)
4242
- **Console capabilities** — Browse Bailian apps (`app list`), check free-tier quota (`usage free`), view model usage statistics (`usage stats`), manage workspaces (`workspace list`), and manage rate limits (`quota list/request/check/history`)
4343
- **Local file auto-upload** — Every URL parameter accepts a local path; uploaded to free temp storage with 48-hour validity
4444

@@ -114,10 +114,10 @@ bl auth login --console
114114

115115
# Fine-tune & deploy — a one-shot train-to-serve workflow
116116
bl dataset upload --file ./train.jsonl # Upload a .jsonl dataset (validated first)
117-
bl finetune create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # Local paths auto-upload
117+
bl finetune text create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # Local paths auto-upload
118118
bl finetune watch --job-id ft-xxx --output json # Non-blocking status probe (exit 0/1/3 = done/failed/running)
119119
bl finetune capability --model qwen3-8b # Which training types a model supports
120-
bl deploy create --model qwen3-8b --name my-svc --plan mu # Deploy the trained model as an endpoint
120+
bl deploy text create --model qwen3-8b --name my-svc --plan mu # Deploy the trained model as an endpoint
121121

122122
# Browse apps / free-tier quota / usage statistics / workspaces
123123
bl app list

README.zh.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ _专为 AI Agent 打造,每个命令均可作为结构化工具调用。_
3838
- **MCP 集成** — 统一调度百炼 MCP 服务:列出服务、查看工具、直接在终端调用任意工具
3939
- **联网搜索** — 实时互联网信息检索,提升回答准确性及时效性
4040
- **模型推荐** — 描述你的场景,智能推荐最适合的模型;支持限定范围搜索、模型对比和替代发现
41-
- **微调与部署** — 上传数据集、创建 SFT/LoRA/DPO/CPT 调优任务`finetune create`)、非阻塞探测任务状态(`finetune watch`)、按模型查训练能力(`finetune capability`),并把训练好的模型部署为推理服务(`deploy create`
41+
- **微调与部署** — 上传数据集、创建文本/音频/图像调优任务`finetune text|audio|image create`;文本涵盖 SFT/LoRA/DPO/CPT)、非阻塞探测任务状态(`finetune watch`)、按模型查训练能力(`finetune capability`),并把训练好的模型部署为推理服务(`deploy text|audio|image create`
4242
- **控制台能力** — 浏览百炼应用(`app list`),查询模型免费额度(`usage free`),查看模型用量统计(`usage stats`),管理业务空间(`workspace list`),管理限流与提额(`quota list/request/check/history`
4343
- **本地文件自动上传** — 所有 URL 参数同时支持本地路径,免费临时存储 48 小时
4444

@@ -112,10 +112,10 @@ bl auth login --console
112112

113113
# 微调与部署 — 从训练到服务的一站式流程
114114
bl dataset upload --file ./train.jsonl # 上传 .jsonl 数据集(先校验)
115-
bl finetune create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # 本地路径自动上传
115+
bl finetune text create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # 本地路径自动上传
116116
bl finetune watch --job-id ft-xxx --output json # 非阻塞状态探测(退出码 0/1/3 = 成功/失败/进行中)
117117
bl finetune capability --model qwen3-8b # 查询模型支持哪些训练方式
118-
bl deploy create --model qwen3-8b --name my-svc --plan mu # 把训练好的模型部署为推理服务
118+
bl deploy text create --model qwen3-8b --name my-svc --plan mu # 把训练好的模型部署为推理服务
119119

120120
# 浏览应用 / 免费额度 / 用量统计 / 业务空间
121121
bl app list

packages/cli/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ Equip your AI Agent out-of-the-box with these capabilities, composable across co
3838
- **MCP integration** — Orchestrate Bailian MCP servers: list services, inspect tools, and invoke any tool directly from the terminal
3939
- **Web search** — Real-time internet retrieval for up-to-date, accurate answers
4040
- **Model recommendation** — Describe your scenario and get best-fit model suggestions; supports scoped search, model comparison, and alternative discovery
41-
- **Fine-tuning & deployment** — Upload datasets, create SFT/LoRA/DPO/CPT jobs (`finetune create`), probe job status non-blockingly (`finetune watch`), query per-model training capability (`finetune capability`), and deploy trained models as endpoints (`deploy create`)
41+
- **Fine-tuning & deployment** — Upload datasets, create text/audio/image fine-tune jobs (`finetune text|audio|image create`; text covers SFT/LoRA/DPO/CPT), probe job status non-blockingly (`finetune watch`), query per-model training capability (`finetune capability`), and deploy trained models as endpoints (`deploy text|audio|image create`)
4242
- **Console capabilities** — Browse Bailian apps (`app list`), check free-tier quota (`usage free`), view model usage statistics (`usage stats`), manage workspaces (`workspace list`), and manage rate limits (`quota list/request/check/history`)
4343
- **Local file auto-upload** — Every URL parameter accepts a local path; uploaded to free temp storage with 48-hour validity
4444

@@ -114,10 +114,10 @@ bl auth login --console
114114

115115
# Fine-tune & deploy — a one-shot train-to-serve workflow
116116
bl dataset upload --file ./train.jsonl # Upload a .jsonl dataset (validated first)
117-
bl finetune create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # Local paths auto-upload
117+
bl finetune text create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # Local paths auto-upload
118118
bl finetune watch --job-id ft-xxx --output json # Non-blocking status probe (exit 0/1/3 = done/failed/running)
119119
bl finetune capability --model qwen3-8b # Which training types a model supports
120-
bl deploy create --model qwen3-8b --name my-svc --plan mu # Deploy the trained model as an endpoint
120+
bl deploy text create --model qwen3-8b --name my-svc --plan mu # Deploy the trained model as an endpoint
121121

122122
# Browse apps / free-tier quota / usage statistics / workspaces
123123
bl app list

packages/cli/README.zh.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ _专为 AI Agent 打造,每个命令均可作为结构化工具调用。_
3838
- **MCP 集成** — 统一调度百炼 MCP 服务:列出服务、查看工具、直接在终端调用任意工具
3939
- **联网搜索** — 实时互联网信息检索,提升回答准确性及时效性
4040
- **模型推荐** — 描述你的场景,智能推荐最适合的模型;支持限定范围搜索、模型对比和替代发现
41-
- **微调与部署** — 上传数据集、创建 SFT/LoRA/DPO/CPT 调优任务`finetune create`)、非阻塞探测任务状态(`finetune watch`)、按模型查训练能力(`finetune capability`),并把训练好的模型部署为推理服务(`deploy create`
41+
- **微调与部署** — 上传数据集、创建文本/音频/图像调优任务`finetune text|audio|image create`;文本涵盖 SFT/LoRA/DPO/CPT)、非阻塞探测任务状态(`finetune watch`)、按模型查训练能力(`finetune capability`),并把训练好的模型部署为推理服务(`deploy text|audio|image create`
4242
- **控制台能力** — 浏览百炼应用(`app list`),查询模型免费额度(`usage free`),查看模型用量统计(`usage stats`),管理业务空间(`workspace list`),管理限流与提额(`quota list/request/check/history`
4343
- **本地文件自动上传** — 所有 URL 参数同时支持本地路径,免费临时存储 48 小时
4444

@@ -112,10 +112,10 @@ bl auth login --console
112112

113113
# 微调与部署 — 从训练到服务的一站式流程
114114
bl dataset upload --file ./train.jsonl # 上传 .jsonl 数据集(先校验)
115-
bl finetune create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # 本地路径自动上传
115+
bl finetune text create --model qwen3-8b --datasets ./train.jsonl --training-type sft-lora # 本地路径自动上传
116116
bl finetune watch --job-id ft-xxx --output json # 非阻塞状态探测(退出码 0/1/3 = 成功/失败/进行中)
117117
bl finetune capability --model qwen3-8b # 查询模型支持哪些训练方式
118-
bl deploy create --model qwen3-8b --name my-svc --plan mu # 把训练好的模型部署为推理服务
118+
bl deploy text create --model qwen3-8b --name my-svc --plan mu # 把训练好的模型部署为推理服务
119119

120120
# 浏览应用 / 免费额度 / 用量统计 / 业务空间
121121
bl app list

packages/cli/tests/e2e/deploy.e2e.test.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,11 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: deploy (offline)", () => {
8787
expect(data.body.capacity).toBe(2);
8888
});
8989

90-
test("deploy audio create --dry-run 构造 lora 部署请求体", async () => {
91-
// deploy create does not inspect modality; the split only changes the path.
92-
// The audio subcommand shares the full flag surface and run logic.
90+
test("deploy audio create --dry-run 默认 plan=mu(CosyVoice 部署契约)", async () => {
91+
// Audio (CosyVoice TTS) outputs deploy model-unit-billed: the modality fixes
92+
// the default plan to `mu` (text/image stay `lora`). In dry-run the mu
93+
// strategy skips the catalog lookup, so deploy_spec is omitted and capacity
94+
// falls back to 1 with billing_method POST_PAY.
9395
const { stdout, stderr, exitCode } = await runCli([
9496
"deploy",
9597
"audio",
@@ -103,10 +105,15 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: deploy (offline)", () => {
103105
"json",
104106
]);
105107
expect(exitCode, stderr).toBe(0);
106-
const data = parseStdoutJson<{ action: string; body: { plan: string; name: string } }>(stdout);
108+
const data = parseStdoutJson<{
109+
action: string;
110+
body: { plan: string; name: string; billing_method?: string; capacity?: number };
111+
}>(stdout);
107112
expect(data.action).toBe("deploy.create");
108-
expect(data.body.plan).toBe("lora");
113+
expect(data.body.plan).toBe("mu");
109114
expect(data.body.name).toBe("my-tts");
115+
expect(data.body.billing_method).toBe("POST_PAY");
116+
expect(data.body.capacity).toBe(1);
110117
});
111118

112119
test("deploy scale --dry-run 转发 capacity", async () => {

packages/commands/src/commands/deploy/create.ts

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
createDeployment,
55
pickPlanStrategy,
66
STRATEGIES,
7-
DEFAULT_DEPLOY_PLAN,
7+
defaultDeployPlan,
8+
type DeployModality,
89
type CreateDeploymentRequest,
910
type CreatePlanFlags,
1011
type CommandContext,
@@ -66,7 +67,8 @@ const CREATE_USAGE =
6667
"--model <model_name> --name <display_name> [--plan <plan>] [--deploy-spec <id>] [--capacity <n>] [--billing-method <m>] [--input-tpm <n>] [--output-tpm <n>] [--thinking-output-tpm <n>]";
6768

6869
const CREATE_NOTES = [
69-
"Plan defaults to `lora` (Token-billed). Pass --plan to override.",
70+
"Plan defaults to `lora` (Token-billed) for text/image and `mu` (model-unit-",
71+
"billed) for audio (CosyVoice TTS). Pass --plan to override.",
7072
"For plan=ptu (Token-billed, provisioned throughput), --input-tpm and",
7173
"--output-tpm are required (the platform rejects creation without an",
7274
"explicit ptu_capacity despite the doc listing defaults).",
@@ -77,22 +79,23 @@ const CREATE_NOTES = [
7779
"After creation, status starts at PENDING and transitions to RUNNING.",
7880
"Invoke the deployed model with: bl text chat --model <deployed_model>",
7981
"WARNING: --model is overloaded across commands and refers to DIFFERENT",
80-
"values. `bl deploy create --model` takes the exported model_name (e.g.",
81-
"`qwen3-8b-ft-...`), but the create response also returns a `deployed_model`",
82-
"field (the deployment instance id, e.g. `qwen3-8b-5ecb5f068d79`). The",
83-
"inference call `bl text chat --model` must use the `deployed_model` from",
84-
"the create response — NOT the `model_name` you passed to `deploy create`.",
85-
"Do not reuse the value across the two commands.",
82+
"values. `bl deploy <modality> create --model` takes the exported model_name",
83+
"(e.g. `qwen3-8b-ft-...`), but the create response also returns a",
84+
"`deployed_model` field (the deployment instance id, e.g.",
85+
"`qwen3-8b-5ecb5f068d79`). The inference call `bl text chat --model` must use",
86+
"the `deployed_model` from the create response — NOT the `model_name` you",
87+
"passed to `deploy <modality> create`. Do not reuse the value across the two",
88+
"commands.",
8689
];
8790

8891
/**
8992
* Shared `deploy <modality> create` flag validation. Plan support is
90-
* server-catalog-driven, not modality-scoped, so validation is identical for
91-
* every modality: reject an unknown --plan, then defer to the plan strategy's
92-
* required-flag check.
93+
* server-catalog-driven, so validation is identical for every modality: resolve
94+
* the effective plan (modality-specific default when --plan is omitted), reject
95+
* an unknown --plan, then defer to the plan strategy's required-flag check.
9396
*/
94-
function validateCreate(flags: CreatePlanFlags): string | undefined {
95-
const plan = flags.plan || DEFAULT_DEPLOY_PLAN;
97+
function validateCreate(modality: DeployModality, flags: CreatePlanFlags): string | undefined {
98+
const plan = flags.plan || defaultDeployPlan(modality);
9699
const strategy = STRATEGIES[plan];
97100
if (!strategy) {
98101
return `Unsupported plan "${plan}". Supported plans: ${Object.keys(STRATEGIES).join(", ")}.`;
@@ -102,20 +105,23 @@ function validateCreate(flags: CreatePlanFlags): string | undefined {
102105

103106
/**
104107
* Shared `deploy <modality> create` implementation. deploy create takes a model
105-
* by name and a billing plan — it does NOT inspect data modality, so the run
106-
* logic is identical across text / audio / image. The modality split only
107-
* changes the command path, description and examples; the parameter surface and
108-
* run logic are unchanged.
108+
* by name and a billing plan — it does NOT inspect data modality for the request
109+
* body, so the run logic is identical across text / audio / image. The modality
110+
* only fixes the default plan (audio → mu, text/image → lora) and the command
111+
* path / description / examples.
109112
*
110113
* Plan-specific behaviour (required flags / body assembly / auto-pick) lives in
111114
* core `plans.ts` (`PlanStrategy` + `STRATEGIES`). This file only handles the
112115
* shared envelope: dispatch, dry-run, and result formatting.
113116
*/
114-
async function runCreate(ctx: CommandContext<typeof CREATE_FLAGS>): Promise<void> {
117+
async function runCreate(
118+
modality: DeployModality,
119+
ctx: CommandContext<typeof CREATE_FLAGS>,
120+
): Promise<void> {
115121
const { identity, settings, flags } = ctx;
116122
const model = flags.model as string;
117123
const name = flags.name as string;
118-
const plan = (flags.plan as string | undefined) || DEFAULT_DEPLOY_PLAN;
124+
const plan = (flags.plan as string | undefined) || defaultDeployPlan(modality);
119125
const format = detectOutputFormat(settings.output);
120126

121127
// Plan-specific behaviour is owned by core `plans.ts`. The strategy resolves
@@ -175,24 +181,24 @@ export const deployTextCreate = defineCommand({
175181
"--model qwen3-8b --name my-qwen3 --plan mu --deploy-spec MU1 --capacity 2",
176182
],
177183
notes: CREATE_NOTES,
178-
validate: (flags) => validateCreate(flags),
179-
run: (ctx) => runCreate(ctx),
184+
validate: (flags) => validateCreate("text", flags),
185+
run: (ctx) => runCreate("text", ctx),
180186
});
181187

182-
/** `bl deploy audio create` — deploy an audio (TTS) model. */
188+
/** `bl deploy audio create` — deploy an audio (TTS) model. Defaults to plan=mu. */
183189
export const deployAudioCreate = defineCommand({
184190
description: "Create an audio (TTS) model deployment",
185191
auth: "apiKey",
186192
usageArgs: CREATE_USAGE,
187193
flags: CREATE_FLAGS,
188194
exampleArgs: [
189195
"--model my-cosyvoice-ft --name my-tts",
190-
"--model my-cosyvoice-ft --name my-tts-mu --plan mu",
196+
"--model my-cosyvoice-ft --name my-tts --deploy-spec dps-xxxx --capacity 1",
191197
"--model my-cosyvoice-ft --name my-tts --dry-run",
192198
],
193199
notes: CREATE_NOTES,
194-
validate: (flags) => validateCreate(flags),
195-
run: (ctx) => runCreate(ctx),
200+
validate: (flags) => validateCreate("audio", flags),
201+
run: (ctx) => runCreate("audio", ctx),
196202
});
197203

198204
/** `bl deploy image create` — deploy an image generation model. */
@@ -207,6 +213,6 @@ export const deployImageCreate = defineCommand({
207213
"--model my-wan-ft --name my-wan --dry-run",
208214
],
209215
notes: CREATE_NOTES,
210-
validate: (flags) => validateCreate(flags),
211-
run: (ctx) => runCreate(ctx),
216+
validate: (flags) => validateCreate("image", flags),
217+
run: (ctx) => runCreate("image", ctx),
212218
});

packages/commands/src/commands/deploy/models.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export default defineCommand({
7373
// - custom (fine-tuned): top-level supported_plans: string[]
7474
// - base (catalog): plans: [{plan, templates?, cu_specs?}]
7575
// For json: surface the deployment-relevant fields preserved as a tree, so
76-
// downstream tooling can drive `bl deploy create --template-id <…>` without
77-
// a second round-trip. For text: keep the compact one-line summary.
76+
// downstream tooling can drive `bl deploy <modality> create --deploy-spec <…>`
77+
// without a second round-trip. For text: keep the compact one-line summary.
7878
if (format === "json") {
7979
const items = models.map((model) => {
8080
const out: Record<string, unknown> = {
@@ -92,7 +92,7 @@ export default defineCommand({
9292
planEntry.cu_specs = plan.cu_specs;
9393
}
9494
if (plan.templates && plan.templates.length > 0) {
95-
// Pull the top 6 fields most useful for `bl deploy create`.
95+
// Pull the top 6 fields most useful for `bl deploy <modality> create`.
9696
// Drop noisy/redundant: template_source, template_type,
9797
// template_version, deploy_spec (typically == template_id).
9898
planEntry.templates = plan.templates.map((template) => {

0 commit comments

Comments
 (0)