From dcdaf3ec92b7ef0a97296dcf65a641b81eb7e7d0 Mon Sep 17 00:00:00 2001 From: clh02467605 Date: Tue, 10 Nov 2026 16:47:13 +0800 Subject: [PATCH] fix(omni): switch default model to qwen3.8-omni-flash --- .../commands/src/commands/config/shared.ts | 5 ++- packages/commands/src/commands/omni/chat.ts | 24 +++++++++-- packages/commands/tests/e2e/omni.e2e.test.ts | 41 ++++++++++++++++--- skills/bailian-gen/SKILL.md | 22 +++++----- skills/bailian-gen/reference/omni.md | 34 +++++++-------- 5 files changed, 87 insertions(+), 39 deletions(-) diff --git a/packages/commands/src/commands/config/shared.ts b/packages/commands/src/commands/config/shared.ts index e903d84c0..2f4b78f44 100644 --- a/packages/commands/src/commands/config/shared.ts +++ b/packages/commands/src/commands/config/shared.ts @@ -80,7 +80,7 @@ export const UI_MODEL_DEFAULTS: Record = { default_reference_to_video_model: "wan3.0-video", default_speech_model: "cosyvoice-v3-flash", default_speech_recognition_model: "fun-asr", - default_omni_model: "qwen3.5-omni-plus", + default_omni_model: "qwen3.8-omni-flash", }; /** One selectable model plus a short note on where the CLI uses it. */ @@ -131,7 +131,8 @@ export const UI_MODEL_CATALOG: Record = { { id: "qwen-audio-3.0-asr-flash", role: "Token Plan speech/recognize (ASR)" }, ], default_omni_model: [ - { id: "qwen3.5-omni-plus", role: "omni/chat default" }, + { id: "qwen3.8-omni-flash", role: "omni/chat default · --text-only" }, + { id: "qwen3.5-omni-plus", role: "omni/chat · audio output path (without --text-only)" }, { id: "qwen3-vl-plus", role: "vision/describe · multimodal input" }, ], }; diff --git a/packages/commands/src/commands/omni/chat.ts b/packages/commands/src/commands/omni/chat.ts index 2b1b18180..e311829d7 100644 --- a/packages/commands/src/commands/omni/chat.ts +++ b/packages/commands/src/commands/omni/chat.ts @@ -141,8 +141,10 @@ export default defineCommand({ type: "string", valueHint: "", description: { - "en-US": "Model ID (default: qwen3.5-omni-plus)", - "zh-CN": "模型 ID(默认:qwen3.5-omni-plus)", + "en-US": + "Model ID (default: qwen3.8-omni-flash; when --model is omitted and --text-only is absent, auto-switches to qwen3.5-omni-plus for audio output)", + "zh-CN": + "模型 ID(默认:qwen3.8-omni-flash;省略 --model 且未带 --text-only 时,自动切换为支持音频输出的 qwen3.5-omni-plus)", }, }, system: { @@ -275,12 +277,26 @@ export default defineCommand({ // --- Parse messages --- const userMessages = flags.message ?? []; - const model = flags.model || settings.defaultOmniModel || "qwen3.5-omni-plus"; + // Default to flash; switch to plus when --model is omitted and --text-only is absent (flash has no audio out). + const textOnly = flags.textOnly === true; + let model = flags.model || settings.defaultOmniModel || "qwen3.8-omni-flash"; + if (!flags.model && !textOnly && model === "qwen3.8-omni-flash") { + model = "qwen3.5-omni-plus"; + } const voice = flags.voice || "Tina"; const audioFormat = flags.audioFormat || "wav"; - const textOnly = flags.textOnly === true; const format = settings.output; + // Explicit flash + audio path will be rejected by the server; warn locally without overriding --model. + if (flags.model === "qwen3.8-omni-flash" && !textOnly) { + ctx.output.warning({ + "en-US": + "qwen3.8-omni-flash does not support audio output. Add --text-only, or omit --model to auto-switch to qwen3.5-omni-plus.", + "zh-CN": + "qwen3.8-omni-flash 不支持音频输出。请添加 --text-only,或省略 --model 以自动切换为 qwen3.5-omni-plus。", + }); + } + // --- Build messages array --- const allMessages: ChatMessage[] = []; if (flags.system) { diff --git a/packages/commands/tests/e2e/omni.e2e.test.ts b/packages/commands/tests/e2e/omni.e2e.test.ts index d49ede47e..bf0bc2dd6 100644 --- a/packages/commands/tests/e2e/omni.e2e.test.ts +++ b/packages/commands/tests/e2e/omni.e2e.test.ts @@ -8,6 +8,7 @@ import { parseStdoutJson, runCommandHelp, runCommandE2e, + runCommandInProcess, } from "./helpers.ts"; import { OMNI_ROUTES } from "./topic-routes.ts"; @@ -17,6 +18,36 @@ describe("e2e: omni", () => { expect(exitCode, stderr).toBe(0); expect(stderr).toMatch(/omni|--message|--audio|text-only/i); }); + + test("omni --dry-run 无 --model/--text-only 时自动切换为 qwen3.5-omni-plus 并带 audio modalities", async () => { + const { stdout, stderr, exitCode } = await runCommandInProcess( + OMNI_ROUTES, + ["omni", "--dry-run", "--message", "hi", "--output", "json"], + { DASHSCOPE_API_KEY: "" }, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ + request?: { model?: string; modalities?: string[]; audio?: unknown }; + }>(stdout); + expect(data.request?.model).toBe("qwen3.5-omni-plus"); + expect(data.request?.modalities).toEqual(["text", "audio"]); + expect(data.request?.audio).toBeTruthy(); + }); + + test("omni --dry-run 无 --model 且带 --text-only 时使用 qwen3.8-omni-flash 且无 modalities", async () => { + const { stdout, stderr, exitCode } = await runCommandInProcess( + OMNI_ROUTES, + ["omni", "--dry-run", "--text-only", "--message", "hi", "--output", "json"], + { DASHSCOPE_API_KEY: "" }, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ + request?: { model?: string; modalities?: string[]; audio?: unknown }; + }>(stdout); + expect(data.request?.model).toBe("qwen3.8-omni-flash"); + expect(data.request?.modalities).toBeUndefined(); + expect(data.request?.audio).toBeUndefined(); + }); }); describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( @@ -38,7 +69,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( const { stderr, exitCode } = await runCommandE2e(OMNI_ROUTES, [ "omni", "--model", - "qwen3.5-omni-flash", + "qwen3.8-omni-flash", ]); expect(exitCode).toBe(2); expect(stderr).toMatch(/--message|Usage:/i); @@ -48,7 +79,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( const { stderr, exitCode } = await runCommandE2e(OMNI_ROUTES, [ "omni", "--model", - "qwen3.5-omni-flash", + "qwen3.8-omni-flash", "--audio", "https://example.com/sample.flac", "--text-only", @@ -64,7 +95,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( "omni", "--dry-run", "--model", - "qwen3.5-omni-flash", + "qwen3.8-omni-flash", "--audio", "https://example.com/sample.wav", "--text-only", @@ -95,7 +126,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( expect(audioPart?.input_audio?.format).toBe("wav"); }); - test("【qwen3.5-omni-flash】本地音频理解", async () => { + test("【qwen3.8-omni-flash】本地音频理解", async () => { const outDir = makeE2eOutputDir(e2eLabelFromMetaUrl(import.meta.url)); const clipText = "端到端Omni音频测试"; const clipWav = join(outDir, "e2e-omni-input.wav"); @@ -121,7 +152,7 @@ describe.skipIf(!isBailianE2EMediaEnabled() || !isDashScopeE2EReady())( const omni = await runCommandE2e(OMNI_ROUTES, [ "omni", "--model", - "qwen3.5-omni-flash", + "qwen3.8-omni-flash", "--audio", clipWav, "--text-only", diff --git a/skills/bailian-gen/SKILL.md b/skills/bailian-gen/SKILL.md index ae0027ea0..e330d7994 100644 --- a/skills/bailian-gen/SKILL.md +++ b/skills/bailian-gen/SKILL.md @@ -35,17 +35,17 @@ BAILIAN_CALLER_TYPE=agent BAILIAN_CALLER_NAME=codex BAILIAN_SKILL_NAME=bailian-g ## When to use which command -| User intent | Command | Default model | -| ---------------------------------------- | ----------------------------------------- | --------------------------------------------------- | -| Text-to-image | `bl image generate` | `qwen-image-3.0` | -| Image edit / multi-image merge | `bl image edit` (repeat `--image`) | `qwen-image-3.0` | -| Text-to-video / image-to-video | `bl video generate` | `wan3.0-video` | -| Video edit / style transfer | `bl video edit` | `happyhorse-1.0-video-edit` | -| Reference-to-video + voice | `bl video ref` | `wan3.0-video` | -| Speech synthesis (TTS / voiceover) | `bl speech synthesize` | `cosyvoice-v3-flash` | -| Speech recognition (ASR / transcription) | `bl speech recognize` | `fun-asr` | -| Image describe | `bl vision describe` | `qwen3-vl-plus`;宿主能做且未点名 → host-first | -| Video / A-V understand | `bl vision describe --video` 或 `bl omni` | 视频理解默认走百炼;`omni` 默认 `qwen3.5-omni-plus` | +| User intent | Command | Default model | +| ---------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | +| Text-to-image | `bl image generate` | `qwen-image-3.0` | +| Image edit / multi-image merge | `bl image edit` (repeat `--image`) | `qwen-image-3.0` | +| Text-to-video / image-to-video | `bl video generate` | `wan3.0-video` | +| Video edit / style transfer | `bl video edit` | `happyhorse-1.0-video-edit` | +| Reference-to-video + voice | `bl video ref` | `wan3.0-video` | +| Speech synthesis (TTS / voiceover) | `bl speech synthesize` | `cosyvoice-v3-flash` | +| Speech recognition (ASR / transcription) | `bl speech recognize` | `fun-asr` | +| Image describe | `bl vision describe` | `qwen3-vl-plus`;宿主能做且未点名 → host-first | +| Video / A-V understand | `bl vision describe --video` 或 `bl omni` | 视频理解默认走百炼;`omni` 默认 `qwen3.8-omni-flash`,省略 `--model` 且无 `--text-only` 时自动切换 `qwen3.5-omni-plus` | Unless the user explicitly specifies a model, omit `--model` and let the CLI use the active Profile’s default. diff --git a/skills/bailian-gen/reference/omni.md b/skills/bailian-gen/reference/omni.md index ff2debef2..7dc733a12 100644 --- a/skills/bailian-gen/reference/omni.md +++ b/skills/bailian-gen/reference/omni.md @@ -24,23 +24,23 @@ Index: [index.md](index.md) #### Flags -| Flag | Type | Required | Description | -| ---------------------- | ------ | -------- | --------------------------------------------------------------------- | -| `--message ` | array | no | Message text (repeatable, prefix role: to set role) | -| `--model ` | string | no | Model ID (default: qwen3.5-omni-plus) | -| `--system ` | string | no | System prompt | -| `--image ` | array | no | Image URL or local file (repeatable) | -| `--audio ` | array | no | Audio URL or local file (.wav/.mp3/.amr/.aac/.m4a/.ogg/.3gp/.3gpp) | -| `--video ` | array | no | Video file URL / local path, or comma-separated frame URLs | -| `--voice ` | string | no | Output voice ID (default: Tina). Use --list-voices to see all options | -| `--list-voices` | switch | no | List available output voices and exit | -| `--audio-format ` | string | no | Audio output format (default: wav) | -| `--audio-out ` | string | no | Save audio to file (default: auto-generate) | -| `--text-only` | switch | no | Output text only, no audio generation | -| `--max-tokens ` | number | no | Maximum tokens to generate | -| `--temperature ` | number | no | Sampling temperature (0.0, 2.0] | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | +| Flag | Type | Required | Description | +| ---------------------- | ------ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `--message ` | array | no | Message text (repeatable, prefix role: to set role) | +| `--model ` | string | no | Model ID (default: qwen3.8-omni-flash; when --model is omitted and --text-only is absent, auto-switches to qwen3.5-omni-plus for audio output) | +| `--system ` | string | no | System prompt | +| `--image ` | array | no | Image URL or local file (repeatable) | +| `--audio ` | array | no | Audio URL or local file (.wav/.mp3/.amr/.aac/.m4a/.ogg/.3gp/.3gpp) | +| `--video ` | array | no | Video file URL / local path, or comma-separated frame URLs | +| `--voice ` | string | no | Output voice ID (default: Tina). Use --list-voices to see all options | +| `--list-voices` | switch | no | List available output voices and exit | +| `--audio-format ` | string | no | Audio output format (default: wav) | +| `--audio-out ` | string | no | Save audio to file (default: auto-generate) | +| `--text-only` | switch | no | Output text only, no audio generation | +| `--max-tokens ` | number | no | Maximum tokens to generate | +| `--temperature ` | number | no | Sampling temperature (0.0, 2.0] | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | #### Examples