mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
feat: update image default model
This commit is contained in:
@@ -26,7 +26,7 @@ Equip your AI Agent out-of-the-box with these capabilities, composable across co
|
|||||||
|
|
||||||
- **Text chat** — Qwen3.8-max: major gains in agentic coding, frontend coding, and vibe coding
|
- **Text chat** — Qwen3.8-max: major gains in agentic coding, frontend coding, and vibe coding
|
||||||
- **Multimodal (Omni)** — Full omni-modal support across text + image + audio + video
|
- **Multimodal (Omni)** — Full omni-modal support across text + image + audio + video
|
||||||
- **Image generation & editing** — Qwen-Image 2.0: pro text rendering, photorealism, strong semantic adherence, multi-image composition
|
- **Image generation & editing** — Qwen-Image 3.0: pro text rendering, photorealism, strong semantic adherence, multi-image composition
|
||||||
- **Video generation & editing** — happyhorse-1.1 series: text-/image-/reference-to-video and natural-language video editing (up to 9-image reference)
|
- **Video generation & editing** — happyhorse-1.1 series: text-/image-/reference-to-video and natural-language video editing (up to 9-image reference)
|
||||||
- **Speech synthesis & recognition** — CosyVoice streaming TTS, voice cloning from 5–20s samples; FunAudio-ASR covers 30 languages including 7 Chinese dialects and 20+ Mandarin accents
|
- **Speech synthesis & recognition** — CosyVoice streaming TTS, voice cloning from 5–20s samples; FunAudio-ASR covers 30 languages including 7 Chinese dialects and 20+ Mandarin accents
|
||||||
- **Image & video understanding** — Qwen-VL: long-form video analysis, chart/document parsing, visual reasoning, multilingual OCR
|
- **Image & video understanding** — Qwen-VL: long-form video analysis, chart/document parsing, visual reasoning, multilingual OCR
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ _专为 AI Agent 打造,每个命令均可作为结构化工具调用。_
|
|||||||
|
|
||||||
- **文本对话** — Qwen3.8-max:Agentic coding、前端编程、Vibe coding 等能力显著增强
|
- **文本对话** — Qwen3.8-max:Agentic coding、前端编程、Vibe coding 等能力显著增强
|
||||||
- **全模态对话** — 文本 + 图像 + 音频 + 视频全模态支持
|
- **全模态对话** — 文本 + 图像 + 音频 + 视频全模态支持
|
||||||
- **图像生成与编辑** — Qwen-Image 2.0:专业文字渲染、真实质感、强语义遵循、多图合成
|
- **图像生成与编辑** — Qwen-Image 3.0:专业文字渲染、真实质感、强语义遵循、多图合成
|
||||||
- **视频生成与编辑** — happyhorse-1.1 系列,支持文生 / 图生 / 参考生(最多 9 张图参考)/ 自然语言视频编辑
|
- **视频生成与编辑** — happyhorse-1.1 系列,支持文生 / 图生 / 参考生(最多 9 张图参考)/ 自然语言视频编辑
|
||||||
- **语音合成与识别** — CosyVoice 实时流式合成,5-20s 样本即可克隆;FunAudio-ASR 覆盖 30 种语种,含汉语七大方言与 20+ 口音官话
|
- **语音合成与识别** — CosyVoice 实时流式合成,5-20s 样本即可克隆;FunAudio-ASR 覆盖 30 种语种,含汉语七大方言与 20+ 口音官话
|
||||||
- **图像与视频理解** — Qwen-VL:长视频解析、复杂图表与文档识别、视觉推理、多语种 OCR
|
- **图像与视频理解** — Qwen-VL:长视频解析、复杂图表与文档识别、视觉推理、多语种 OCR
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Equip your AI Agent out-of-the-box with these capabilities, composable across co
|
|||||||
|
|
||||||
- **Text chat** — Qwen3.8-max: major gains in agentic coding, frontend coding, and vibe coding
|
- **Text chat** — Qwen3.8-max: major gains in agentic coding, frontend coding, and vibe coding
|
||||||
- **Multimodal (Omni)** — Full omni-modal support across text + image + audio + video
|
- **Multimodal (Omni)** — Full omni-modal support across text + image + audio + video
|
||||||
- **Image generation & editing** — Qwen-Image 2.0: pro text rendering, photorealism, strong semantic adherence, multi-image composition
|
- **Image generation & editing** — Qwen-Image 3.0: pro text rendering, photorealism, strong semantic adherence, multi-image composition
|
||||||
- **Video generation & editing** — happyhorse-1.1 series: text-/image-/reference-to-video and natural-language video editing (up to 9-image reference)
|
- **Video generation & editing** — happyhorse-1.1 series: text-/image-/reference-to-video and natural-language video editing (up to 9-image reference)
|
||||||
- **Speech synthesis & recognition** — CosyVoice streaming TTS, voice cloning from 5–20s samples; FunAudio-ASR covers 30 languages including 7 Chinese dialects and 20+ Mandarin accents
|
- **Speech synthesis & recognition** — CosyVoice streaming TTS, voice cloning from 5–20s samples; FunAudio-ASR covers 30 languages including 7 Chinese dialects and 20+ Mandarin accents
|
||||||
- **Image & video understanding** — Qwen-VL: long-form video analysis, chart/document parsing, visual reasoning, multilingual OCR
|
- **Image & video understanding** — Qwen-VL: long-form video analysis, chart/document parsing, visual reasoning, multilingual OCR
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ _专为 AI Agent 打造,每个命令均可作为结构化工具调用。_
|
|||||||
|
|
||||||
- **文本对话** — Qwen3.8-max:Agentic coding、前端编程、Vibe coding 等能力显著增强
|
- **文本对话** — Qwen3.8-max:Agentic coding、前端编程、Vibe coding 等能力显著增强
|
||||||
- **全模态对话** — 文本 + 图像 + 音频 + 视频全模态支持
|
- **全模态对话** — 文本 + 图像 + 音频 + 视频全模态支持
|
||||||
- **图像生成与编辑** — Qwen-Image 2.0:专业文字渲染、真实质感、强语义遵循、多图合成
|
- **图像生成与编辑** — Qwen-Image 3.0:专业文字渲染、真实质感、强语义遵循、多图合成
|
||||||
- **视频生成与编辑** — happyhorse-1.1 系列,支持文生 / 图生 / 参考生(最多 9 张图参考)/ 自然语言视频编辑
|
- **视频生成与编辑** — happyhorse-1.1 系列,支持文生 / 图生 / 参考生(最多 9 张图参考)/ 自然语言视频编辑
|
||||||
- **语音合成与识别** — CosyVoice 实时流式合成,5-20s 样本即可克隆;FunAudio-ASR 覆盖 30 种语种,含汉语七大方言与 20+ 口音官话
|
- **语音合成与识别** — CosyVoice 实时流式合成,5-20s 样本即可克隆;FunAudio-ASR 覆盖 30 种语种,含汉语七大方言与 20+ 口音官话
|
||||||
- **图像与视频理解** — Qwen-VL:长视频解析、复杂图表与文档识别、视觉推理、多语种 OCR
|
- **图像与视频理解** — Qwen-VL:长视频解析、复杂图表与文档识别、视觉推理、多语种 OCR
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export const UI_BOOLEAN_KEYS = new Set<string>(["telemetry"]);
|
|||||||
// without persisting a value that would pin the model.
|
// without persisting a value that would pin the model.
|
||||||
export const UI_MODEL_DEFAULTS: Record<string, string> = {
|
export const UI_MODEL_DEFAULTS: Record<string, string> = {
|
||||||
default_text_model: "qwen3.8-max",
|
default_text_model: "qwen3.8-max",
|
||||||
default_image_model: "qwen-image-2.0",
|
default_image_model: "qwen-image-3.0",
|
||||||
default_video_model: "happyhorse-1.1-t2v",
|
default_video_model: "happyhorse-1.1-t2v",
|
||||||
default_speech_model: "cosyvoice-v3-flash",
|
default_speech_model: "cosyvoice-v3-flash",
|
||||||
default_omni_model: "qwen3.5-omni-plus",
|
default_omni_model: "qwen3.5-omni-plus",
|
||||||
@@ -86,7 +86,8 @@ export const UI_MODEL_CATALOG: Record<string, ModelOption[]> = {
|
|||||||
{ id: "qwen3.6-flash", role: "fast · advisor intent" },
|
{ id: "qwen3.6-flash", role: "fast · advisor intent" },
|
||||||
],
|
],
|
||||||
default_image_model: [
|
default_image_model: [
|
||||||
{ id: "qwen-image-2.0", role: "image/generate default · sync" },
|
{ id: "qwen-image-3.0", role: "image/generate default · sync" },
|
||||||
|
{ id: "qwen-image-2.0", role: "image/generate · sync" },
|
||||||
{ id: "qwen-image-max", role: "image/generate · sync" },
|
{ id: "qwen-image-max", role: "image/generate · sync" },
|
||||||
{ id: "qwen-image-edit-2.0", role: "image/edit · sync" },
|
{ id: "qwen-image-edit-2.0", role: "image/edit · sync" },
|
||||||
{ id: "wanx2.x", role: "image/generate · async series" },
|
{ id: "wanx2.x", role: "image/generate · async series" },
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ export default defineCommand({
|
|||||||
"--file photo.jpg --model qwen3-vl-plus",
|
"--file photo.jpg --model qwen3-vl-plus",
|
||||||
"--file video.mp4 --model wan2.1-t2v-plus",
|
"--file video.mp4 --model wan2.1-t2v-plus",
|
||||||
"--file audio.wav --model qwen3-asr-flash",
|
"--file audio.wav --model qwen3-asr-flash",
|
||||||
"--file cat.png --model qwen-image-2.0",
|
"--file cat.png --model qwen-image-3.0",
|
||||||
],
|
],
|
||||||
async run(ctx) {
|
async run(ctx) {
|
||||||
const { settings, flags } = ctx;
|
const { settings, flags } = ctx;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const EDIT_FLAGS = {
|
|||||||
model: {
|
model: {
|
||||||
type: "string",
|
type: "string",
|
||||||
valueHint: "<model>",
|
valueHint: "<model>",
|
||||||
description: "Model ID (default: qwen-image-2.0)",
|
description: "Model ID (default: qwen-image-3.0)",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -123,7 +123,7 @@ export default defineCommand({
|
|||||||
}
|
}
|
||||||
const prompt = flags.prompt;
|
const prompt = flags.prompt;
|
||||||
|
|
||||||
const model = flags.model || settings.defaultImageModel || "qwen-image-2.0";
|
const model = flags.model || settings.defaultImageModel || "qwen-image-3.0";
|
||||||
const route = resolveImageEditApi(model);
|
const route = resolveImageEditApi(model);
|
||||||
|
|
||||||
// Auto-upload local files (resolve all images in parallel)
|
// Auto-upload local files (resolve all images in parallel)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const GENERATE_FLAGS = {
|
|||||||
model: {
|
model: {
|
||||||
type: "string",
|
type: "string",
|
||||||
valueHint: "<model>",
|
valueHint: "<model>",
|
||||||
description: "Model ID (default: qwen-image-2.0)",
|
description: "Model ID (default: qwen-image-3.0)",
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
type: "string",
|
type: "string",
|
||||||
@@ -105,7 +105,7 @@ export default defineCommand({
|
|||||||
const { settings, flags } = ctx;
|
const { settings, flags } = ctx;
|
||||||
const prompt = flags.prompt;
|
const prompt = flags.prompt;
|
||||||
|
|
||||||
const model = flags.model || settings.defaultImageModel || "qwen-image-2.0";
|
const model = flags.model || settings.defaultImageModel || "qwen-image-3.0";
|
||||||
const route = resolveImageGenerateApi(model);
|
const route = resolveImageGenerateApi(model);
|
||||||
const defaultSize = "1:1";
|
const defaultSize = "1:1";
|
||||||
const sizeInput = flags.size || defaultSize;
|
const sizeInput = flags.size || defaultSize;
|
||||||
|
|||||||
@@ -89,13 +89,13 @@ test("GET /api/config 返回全部 profile、明文密钥与持久化激活项",
|
|||||||
expect(res.json.enums.console_site).toEqual(["domestic", "international"]);
|
expect(res.json.enums.console_site).toEqual(["domestic", "international"]);
|
||||||
expect(res.json.booleanKeys).toContain("telemetry");
|
expect(res.json.booleanKeys).toContain("telemetry");
|
||||||
// Default field hints are surfaced as prefilled values in the UI.
|
// Default field hints are surfaced as prefilled values in the UI.
|
||||||
expect(res.json.fieldDefaults.default_image_model).toBe("qwen-image-2.0");
|
expect(res.json.fieldDefaults.default_image_model).toBe("qwen-image-3.0");
|
||||||
expect(res.json.fieldDefaults.default_text_model).toBe("qwen3.8-max");
|
expect(res.json.fieldDefaults.default_text_model).toBe("qwen3.8-max");
|
||||||
expect(res.json.fieldDefaults.output_dir).toContain("bailian-output");
|
expect(res.json.fieldDefaults.output_dir).toContain("bailian-output");
|
||||||
expect(res.json.fieldDefaults.timeout).toBe("300");
|
expect(res.json.fieldDefaults.timeout).toBe("300");
|
||||||
expect(res.json.fieldDefaults.base_url).toBe("https://dashscope.aliyuncs.com");
|
expect(res.json.fieldDefaults.base_url).toBe("https://dashscope.aliyuncs.com");
|
||||||
// Per-category model catalog (click-to-fill suggestions) is exposed too.
|
// Per-category model catalog (click-to-fill suggestions) is exposed too.
|
||||||
expect(res.json.modelCatalog.default_image_model[0]).toMatchObject({ id: "qwen-image-2.0" });
|
expect(res.json.modelCatalog.default_image_model[0]).toMatchObject({ id: "qwen-image-3.0" });
|
||||||
expect(res.json.modelCatalog.default_video_model.map((m: { id: string }) => m.id)).toContain(
|
expect(res.json.modelCatalog.default_video_model.map((m: { id: string }) => m.id)).toContain(
|
||||||
"happyhorse-1.1-i2v",
|
"happyhorse-1.1-i2v",
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -194,13 +194,13 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())("e2e: ima
|
|||||||
expect(stderr).toMatch(/--prompt|Usage:/i);
|
expect(stderr).toMatch(/--prompt|Usage:/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("【qwen-image-2.0】图片编辑", async () => {
|
test("【qwen-image-3.0】图片编辑", async () => {
|
||||||
const outDir = makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url));
|
const outDir = makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url));
|
||||||
const gen = await runCommandE2e(IMAGE_ROUTES, [
|
const gen = await runCommandE2e(IMAGE_ROUTES, [
|
||||||
"image",
|
"image",
|
||||||
"generate",
|
"generate",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
"--prompt",
|
"--prompt",
|
||||||
"一只简笔画小猫,白底",
|
"一只简笔画小猫,白底",
|
||||||
"--out-dir",
|
"--out-dir",
|
||||||
@@ -220,7 +220,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())("e2e: ima
|
|||||||
"image",
|
"image",
|
||||||
"edit",
|
"edit",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
"--image",
|
"--image",
|
||||||
imagePath!,
|
imagePath!,
|
||||||
"--prompt",
|
"--prompt",
|
||||||
|
|||||||
@@ -202,19 +202,19 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())(
|
|||||||
"image",
|
"image",
|
||||||
"generate",
|
"generate",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
]);
|
]);
|
||||||
expect(exitCode).toBe(2);
|
expect(exitCode).toBe(2);
|
||||||
expect(stderr).toMatch(/--prompt|Usage:/i);
|
expect(stderr).toMatch(/--prompt|Usage:/i);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("【qwen-image-2.0】图片生成", async () => {
|
test("【qwen-image-3.0】图片生成", async () => {
|
||||||
const outDir = makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url));
|
const outDir = makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url));
|
||||||
const { stdout, stderr, exitCode } = await runCommandE2e(IMAGE_ROUTES, [
|
const { stdout, stderr, exitCode } = await runCommandE2e(IMAGE_ROUTES, [
|
||||||
"image",
|
"image",
|
||||||
"generate",
|
"generate",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
"--prompt",
|
"--prompt",
|
||||||
"一只简笔画小猫,白底",
|
"一只简笔画小猫,白底",
|
||||||
"--out-dir",
|
"--out-dir",
|
||||||
|
|||||||
@@ -159,7 +159,7 @@ describe.skipIf(!isBailianE2EVideoEnabled() || !isDashScopeE2EReady())(
|
|||||||
"image",
|
"image",
|
||||||
"generate",
|
"generate",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
"--prompt",
|
"--prompt",
|
||||||
"一只简笔画小猫,白底",
|
"一只简笔画小猫,白底",
|
||||||
"--out-dir",
|
"--out-dir",
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ describe.skipIf(!isBailianE2EVideoEnabled() || !isDashScopeE2EReady())(
|
|||||||
"image",
|
"image",
|
||||||
"generate",
|
"generate",
|
||||||
"--model",
|
"--model",
|
||||||
"qwen-image-2.0",
|
"qwen-image-3.0",
|
||||||
"--prompt",
|
"--prompt",
|
||||||
"一片绿色的树叶,白底",
|
"一片绿色的树叶,白底",
|
||||||
"--out-dir",
|
"--out-dir",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { image2ImagePath, imagePath, imageSyncPath, imageText2ImagePath } from "
|
|||||||
* - async text2image + prompt: wan2.5/2.2/2.1-t2i*, wanx*-t2i*
|
* - async text2image + prompt: wan2.5/2.2/2.1-t2i*, wanx*-t2i*
|
||||||
*
|
*
|
||||||
* Edit (I2I):
|
* Edit (I2I):
|
||||||
* - sync multimodal + messages(+images): qwen-image-2.0*, qwen-image-edit*, wan2.6-image*, wan2.7-image*
|
* - sync multimodal + messages(+images): qwen-image-3.0*, qwen-image-2.0*, qwen-image-edit*, wan2.6-image*, wan2.7-image*
|
||||||
* (pure T2I models such as z-image / qwen-image-plus / qwen-image-max are NOT edit models)
|
* (pure T2I models such as z-image / qwen-image-plus / qwen-image-max are NOT edit models)
|
||||||
* - async image2image + prompt/images: wan2.5-i2i*
|
* - async image2image + prompt/images: wan2.5-i2i*
|
||||||
* - async image2image + function/base_image_url: *imageedit* (e.g. wanx2.1-imageedit)
|
* - async image2image + function/base_image_url: *imageedit* (e.g. wanx2.1-imageedit)
|
||||||
@@ -60,6 +60,7 @@ const SYNC_GENERATE_PREFIXES = ["qwen-image", "wan2.7-image", "z-image"] as cons
|
|||||||
* Pure T2I models (z-image / qwen-image-plus / qwen-image-max) are excluded.
|
* Pure T2I models (z-image / qwen-image-plus / qwen-image-max) are excluded.
|
||||||
*/
|
*/
|
||||||
const SYNC_EDIT_PREFIXES = [
|
const SYNC_EDIT_PREFIXES = [
|
||||||
|
"qwen-image-3.0",
|
||||||
"qwen-image-2.0",
|
"qwen-image-2.0",
|
||||||
"qwen-image-edit",
|
"qwen-image-edit",
|
||||||
"wan2.7-image",
|
"wan2.7-image",
|
||||||
@@ -109,7 +110,12 @@ export function isWanxFunctionImageEditModel(model: string): boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resolveImageSizeProfile(model: string): ImageSizeProfile {
|
export function resolveImageSizeProfile(model: string): ImageSizeProfile {
|
||||||
if (model.startsWith("qwen-image-2.0") || model.startsWith("qwen-image-edit")) {
|
// 3.0 暂复用 2.0 高分比例表(CLI ratio→像素便捷映射);不做独立 3.0 profile。
|
||||||
|
if (
|
||||||
|
model.startsWith("qwen-image-3.0") ||
|
||||||
|
model.startsWith("qwen-image-2.0") ||
|
||||||
|
model.startsWith("qwen-image-edit")
|
||||||
|
) {
|
||||||
return "qwen-image-2.0";
|
return "qwen-image-2.0";
|
||||||
}
|
}
|
||||||
// Remaining qwen-image* (plus / max / bare qwen-image) share the fixed table.
|
// Remaining qwen-image* (plus / max / bare qwen-image) share the fixed table.
|
||||||
@@ -133,7 +139,13 @@ export function resolveImageSizeProfile(model: string): ImageSizeProfile {
|
|||||||
|
|
||||||
/** Official / CLI defaults for prompt_extend when the flag is omitted. */
|
/** Official / CLI defaults for prompt_extend when the flag is omitted. */
|
||||||
export function resolvePromptExtendDefault(model: string): boolean | undefined {
|
export function resolvePromptExtendDefault(model: string): boolean | undefined {
|
||||||
if (model.startsWith("qwen-image-2.0") || model.startsWith("qwen-image-max")) return true;
|
if (
|
||||||
|
model.startsWith("qwen-image-3.0") ||
|
||||||
|
model.startsWith("qwen-image-2.0") ||
|
||||||
|
model.startsWith("qwen-image-max")
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
// Z-Image docs default prompt_extend to false.
|
// Z-Image docs default prompt_extend to false.
|
||||||
if (model.startsWith("z-image")) return false;
|
if (model.startsWith("z-image")) return false;
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from "../src/client/image-routes.ts";
|
} from "../src/client/image-routes.ts";
|
||||||
|
|
||||||
test("sync multimodal family covers qwen-image, wan2.6/2.7 image, and z-image", () => {
|
test("sync multimodal family covers qwen-image, wan2.6/2.7 image, and z-image", () => {
|
||||||
|
expect(isSyncMultimodalImageModel("qwen-image-3.0")).toBe(true);
|
||||||
expect(isSyncMultimodalImageModel("qwen-image-2.0")).toBe(true);
|
expect(isSyncMultimodalImageModel("qwen-image-2.0")).toBe(true);
|
||||||
expect(isSyncMultimodalImageModel("qwen-image-2.0-pro")).toBe(true);
|
expect(isSyncMultimodalImageModel("qwen-image-2.0-pro")).toBe(true);
|
||||||
expect(isSyncMultimodalImageModel("qwen-image-plus")).toBe(true);
|
expect(isSyncMultimodalImageModel("qwen-image-plus")).toBe(true);
|
||||||
@@ -41,6 +42,7 @@ test("legacy image2image is wan2.5-i2i only; wanx imageedit uses function protoc
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("size profiles are model-specific, not sync/async", () => {
|
test("size profiles are model-specific, not sync/async", () => {
|
||||||
|
expect(resolveImageSizeProfile("qwen-image-3.0")).toBe("qwen-image-2.0");
|
||||||
expect(resolveImageSizeProfile("qwen-image-2.0")).toBe("qwen-image-2.0");
|
expect(resolveImageSizeProfile("qwen-image-2.0")).toBe("qwen-image-2.0");
|
||||||
expect(resolveImageSizeProfile("qwen-image")).toBe("qwen-image-fixed");
|
expect(resolveImageSizeProfile("qwen-image")).toBe("qwen-image-fixed");
|
||||||
expect(resolveImageSizeProfile("qwen-image-plus")).toBe("qwen-image-fixed");
|
expect(resolveImageSizeProfile("qwen-image-plus")).toBe("qwen-image-fixed");
|
||||||
@@ -55,6 +57,7 @@ test("size profiles are model-specific, not sync/async", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("prompt_extend defaults follow model docs", () => {
|
test("prompt_extend defaults follow model docs", () => {
|
||||||
|
expect(resolvePromptExtendDefault("qwen-image-3.0")).toBe(true);
|
||||||
expect(resolvePromptExtendDefault("qwen-image-2.0")).toBe(true);
|
expect(resolvePromptExtendDefault("qwen-image-2.0")).toBe(true);
|
||||||
expect(resolvePromptExtendDefault("qwen-image-max")).toBe(true);
|
expect(resolvePromptExtendDefault("qwen-image-max")).toBe(true);
|
||||||
expect(resolvePromptExtendDefault("z-image-turbo")).toBe(false);
|
expect(resolvePromptExtendDefault("z-image-turbo")).toBe(false);
|
||||||
@@ -85,6 +88,11 @@ test("resolveImageGenerateApi picks path, input style, and size profile", () =>
|
|||||||
kind: "async-image-generation",
|
kind: "async-image-generation",
|
||||||
sizeProfile: "wan26",
|
sizeProfile: "wan26",
|
||||||
});
|
});
|
||||||
|
expect(resolveImageGenerateApi("qwen-image-3.0")).toMatchObject({
|
||||||
|
kind: "sync-multimodal",
|
||||||
|
sizeProfile: "qwen-image-2.0",
|
||||||
|
promptExtendDefault: true,
|
||||||
|
});
|
||||||
expect(resolveImageGenerateApi("qwen-image-2.0")).toMatchObject({
|
expect(resolveImageGenerateApi("qwen-image-2.0")).toMatchObject({
|
||||||
kind: "sync-multimodal",
|
kind: "sync-multimodal",
|
||||||
sizeProfile: "qwen-image-2.0",
|
sizeProfile: "qwen-image-2.0",
|
||||||
@@ -115,6 +123,10 @@ test("resolveImageEditApi excludes pure T2I models from sync edit", () => {
|
|||||||
kind: "sync-multimodal",
|
kind: "sync-multimodal",
|
||||||
useSync: true,
|
useSync: true,
|
||||||
});
|
});
|
||||||
|
expect(resolveImageEditApi("qwen-image-3.0")).toMatchObject({
|
||||||
|
kind: "sync-multimodal",
|
||||||
|
useSync: true,
|
||||||
|
});
|
||||||
expect(resolveImageEditApi("qwen-image-2.0")).toMatchObject({
|
expect(resolveImageEditApi("qwen-image-2.0")).toMatchObject({
|
||||||
kind: "sync-multimodal",
|
kind: "sync-multimodal",
|
||||||
useSync: true,
|
useSync: true,
|
||||||
|
|||||||
@@ -171,7 +171,7 @@ export async function imageGenerate(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = input.model || "qwen-image-2.0";
|
const model = input.model || "qwen-image-3.0";
|
||||||
const route = resolveImageGenerateApi(model);
|
const route = resolveImageGenerateApi(model);
|
||||||
const n = input.n ?? 1;
|
const n = input.n ?? 1;
|
||||||
|
|
||||||
@@ -269,7 +269,7 @@ export async function imageEdit(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const images = Array.isArray(input.image) ? input.image : input.image ? [input.image] : [];
|
const images = Array.isArray(input.image) ? input.image : input.image ? [input.image] : [];
|
||||||
const model = input.model || "qwen-image-2.0";
|
const model = input.model || "qwen-image-3.0";
|
||||||
const route = resolveImageEditApi(model);
|
const route = resolveImageEditApi(model);
|
||||||
const n = input.n ?? 1;
|
const n = input.n ?? 1;
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type { ImageSizeProfile } from "bailian-cli-core";
|
|||||||
* Do not infer size from sync/async — that mismatches model constraints.
|
* Do not infer size from sync/async — that mismatches model constraints.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/** qwen-image-2.0 / qwen-image-edit recommended high-res presets. */
|
/** qwen-image-2.0 / qwen-image-edit recommended high-res presets(3.0 经 profile 复用此表). */
|
||||||
export const QWEN_IMAGE_20_RATIO_MAP: Record<string, string> = {
|
export const QWEN_IMAGE_20_RATIO_MAP: Record<string, string> = {
|
||||||
"16:9": "2688*1536",
|
"16:9": "2688*1536",
|
||||||
"9:16": "1536*2688",
|
"9:16": "1536*2688",
|
||||||
|
|||||||
@@ -45,5 +45,5 @@ bl file upload --file audio.wav --model qwen3-asr-flash
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
bl file upload --file cat.png --model qwen-image-2.0
|
bl file upload --file cat.png --model qwen-image-3.0
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ description: >-
|
|||||||
|
|
||||||
| User intent | Command | Default model |
|
| User intent | Command | Default model |
|
||||||
| --------------------------------------------- | ---------------------------------- | ---------------------------------------------- |
|
| --------------------------------------------- | ---------------------------------- | ---------------------------------------------- |
|
||||||
| Text-to-image | `bl image generate` | `qwen-image-2.0` |
|
| Text-to-image | `bl image generate` | `qwen-image-3.0` |
|
||||||
| Image edit / multi-image merge | `bl image edit` (repeat `--image`) | `qwen-image-2.0` |
|
| Image edit / multi-image merge | `bl image edit` (repeat `--image`) | `qwen-image-3.0` |
|
||||||
| Text-to-video / image-to-video | `bl video generate` | `happyhorse-1.1-t2v` / `-i2v` (with `--image`) |
|
| Text-to-video / image-to-video | `bl video generate` | `happyhorse-1.1-t2v` / `-i2v` (with `--image`) |
|
||||||
| Video edit / style transfer | `bl video edit` | `happyhorse-1.0-video-edit` |
|
| Video edit / style transfer | `bl video edit` | `happyhorse-1.0-video-edit` |
|
||||||
| Reference-to-video + voice | `bl video ref` | `happyhorse-1.1-r2v` |
|
| Reference-to-video + voice | `bl video ref` | `happyhorse-1.1-r2v` |
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ Index: [index.md](index.md)
|
|||||||
| --------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------- |
|
| --------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------- |
|
||||||
| `--image <url>` | array | yes | Source image URL or local file path (repeatable for multi-image merge) |
|
| `--image <url>` | array | yes | Source image URL or local file path (repeatable for multi-image merge) |
|
||||||
| `--prompt <text>` | string | yes | Edit instruction text |
|
| `--prompt <text>` | string | yes | Edit instruction text |
|
||||||
| `--model <model>` | string | no | Model ID (default: qwen-image-2.0) |
|
| `--model <model>` | string | no | Model ID (default: qwen-image-3.0) |
|
||||||
| `--size <W*H>` | string | no | Output image size: ratio (3:4, 16:9) or pixels (2048\*2048) |
|
| `--size <W*H>` | string | no | Output image size: ratio (3:4, 16:9) or pixels (2048\*2048) |
|
||||||
| `--n <count>` | number | no | Number of images (default: 1, max: 6) |
|
| `--n <count>` | number | no | Number of images (default: 1, max: 6) |
|
||||||
| `--seed <n>` | number | no | Random seed for reproducible results |
|
| `--seed <n>` | number | no | Random seed for reproducible results |
|
||||||
@@ -91,7 +91,7 @@ bl image edit --image ./photo.png --prompt "Replace the background with a beach"
|
|||||||
| Flag | Type | Required | Description |
|
| Flag | Type | Required | Description |
|
||||||
| --------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
|
| --------------------------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
|
||||||
| `--prompt <text>` | string | yes | Image description |
|
| `--prompt <text>` | string | yes | Image description |
|
||||||
| `--model <model>` | string | no | Model ID (default: qwen-image-2.0) |
|
| `--model <model>` | string | no | Model ID (default: qwen-image-3.0) |
|
||||||
| `--size <W*H>` | string | no | Image size: ratio (3:4, 16:9, 1:1) or pixels (2048\*2048) |
|
| `--size <W*H>` | string | no | Image size: ratio (3:4, 16:9, 1:1) or pixels (2048\*2048) |
|
||||||
| `--n <count>` | number | no | Number of images per request (default: 1, max: 6) |
|
| `--n <count>` | number | no | Number of images per request (default: 1, max: 6) |
|
||||||
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
| `--seed <n>` | number | no | Random seed for reproducible generation |
|
||||||
|
|||||||
Reference in New Issue
Block a user