Compare commits

..

3 Commits

Author SHA1 Message Date
github-actions[bot]
3fb2529559 chore(release): v0.0.14-nightly.2 2025-09-29 00:17:50 +00:00
Brando Magnani
9fce177bd8 Fix/qwen3 vl plus highres (#721)
* feat: Add Qwen3-VL-Plus token limits (256K input, 32K output)

- Added 256K input context window limit for Qwen3-VL-Plus model
- Updated output token limit from 8K to 32K for Qwen3-VL-Plus
- Added comprehensive tests for both input and output limits

As requested by Qwen maintainers for proper model support.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: enable high-res flag for qwen VL models

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-26 17:20:18 +08:00
Brando Magnani
f7841338c4 feat: Add Qwen3-VL-Plus token limits (256K input, 32K output) (#720)
- Added 256K input context window limit for Qwen3-VL-Plus model
- Updated output token limit from 8K to 32K for Qwen3-VL-Plus
- Added comprehensive tests for both input and output limits

As requested by Qwen maintainers for proper model support.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-26 17:19:54 +08:00
10 changed files with 98 additions and 16 deletions

12
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@qwen-code/qwen-code",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@qwen-code/qwen-code",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"workspaces": [
"packages/*"
],
@@ -13454,7 +13454,7 @@
},
"packages/cli": {
"name": "@qwen-code/qwen-code",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"dependencies": {
"@google/genai": "1.9.0",
"@iarna/toml": "^2.2.5",
@@ -13662,7 +13662,7 @@
},
"packages/core": {
"name": "@qwen-code/qwen-code-core",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"dependencies": {
"@google/genai": "1.13.0",
"@lvce-editor/ripgrep": "^1.6.0",
@@ -13788,7 +13788,7 @@
},
"packages/test-utils": {
"name": "@qwen-code/qwen-code-test-utils",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"dev": true,
"license": "Apache-2.0",
"devDependencies": {
@@ -13800,7 +13800,7 @@
},
"packages/vscode-ide-companion": {
"name": "qwen-code-vscode-ide-companion",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"license": "LICENSE",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.15.1",

View File

@@ -1,6 +1,6 @@
{
"name": "@qwen-code/qwen-code",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"engines": {
"node": ">=20.0.0"
},
@@ -13,7 +13,7 @@
"url": "git+https://github.com/QwenLM/qwen-code.git"
},
"config": {
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.14-nightly.1"
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.14-nightly.2"
},
"scripts": {
"start": "node scripts/start.js",

View File

@@ -1,6 +1,6 @@
{
"name": "@qwen-code/qwen-code",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"description": "Qwen Code",
"repository": {
"type": "git",
@@ -25,7 +25,7 @@
"dist"
],
"config": {
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.14-nightly.1"
"sandboxImageUri": "ghcr.io/qwenlm/qwen-code:0.0.14-nightly.2"
},
"dependencies": {
"@google/genai": "1.9.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@qwen-code/qwen-code-core",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"description": "Qwen Code Core",
"repository": {
"type": "git",

View File

@@ -688,6 +688,60 @@ describe('DashScopeOpenAICompatibleProvider', () => {
).toBe(true); // Vision-specific parameter should be preserved
});
it('should set high resolution flag for qwen3-vl-plus', () => {
const request: OpenAI.Chat.ChatCompletionCreateParams = {
model: 'qwen3-vl-plus',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Please inspect the image.' },
{
type: 'image_url',
image_url: { url: 'https://example.com/vl.jpg' },
},
],
},
],
max_tokens: 50000,
};
const result = provider.buildRequest(request, 'test-prompt-id');
expect(result.max_tokens).toBe(32768);
expect(
(result as { vl_high_resolution_images?: boolean })
.vl_high_resolution_images,
).toBe(true);
});
it('should set high resolution flag for the vision-model alias', () => {
const request: OpenAI.Chat.ChatCompletionCreateParams = {
model: 'vision-model',
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Alias payload' },
{
type: 'image_url',
image_url: { url: 'https://example.com/alias.png' },
},
],
},
],
max_tokens: 9000,
};
const result = provider.buildRequest(request, 'test-prompt-id');
expect(result.max_tokens).toBe(8192);
expect(
(result as { vl_high_resolution_images?: boolean })
.vl_high_resolution_images,
).toBe(true);
});
it('should handle streaming requests with output token limits', () => {
const request: OpenAI.Chat.ChatCompletionCreateParams = {
model: 'qwen3-coder-plus',

View File

@@ -100,7 +100,7 @@ export class DashScopeOpenAICompatibleProvider
request.model,
);
if (request.model.startsWith('qwen-vl')) {
if (this.isVisionModel(request.model)) {
return {
...requestWithTokenLimits,
messages,
@@ -267,6 +267,28 @@ export class DashScopeOpenAICompatibleProvider
return contentArray;
}
private isVisionModel(model: string | undefined): boolean {
if (!model) {
return false;
}
const normalized = model.toLowerCase();
if (normalized === 'vision-model') {
return true;
}
if (normalized.startsWith('qwen-vl')) {
return true;
}
if (normalized.startsWith('qwen3-vl-plus')) {
return true;
}
return false;
}
/**
* Apply output token limit to a request's max_tokens parameter.
*

View File

@@ -278,6 +278,11 @@ describe('tokenLimit with output type', () => {
expect(tokenLimit('qwen-vl-max-latest', 'output')).toBe(8192); // 8K output
});
it('should return different limits for input vs output for qwen3-vl-plus', () => {
expect(tokenLimit('qwen3-vl-plus', 'input')).toBe(262144); // 256K input
expect(tokenLimit('qwen3-vl-plus', 'output')).toBe(32768); // 32K output
});
it('should return same default limits for unknown models', () => {
expect(tokenLimit('unknown-model', 'input')).toBe(DEFAULT_TOKEN_LIMIT); // 128K input
expect(tokenLimit('unknown-model', 'output')).toBe(

View File

@@ -135,6 +135,7 @@ const PATTERNS: Array<[RegExp, TokenCount]> = [
[/^qwen-turbo.*$/, LIMITS['128k']],
// Qwen Vision Models
[/^qwen3-vl-plus$/, LIMITS['256k']], // Qwen3-VL-Plus: 256K input
[/^qwen-vl-max.*$/, LIMITS['128k']],
// Generic vision-model: same as qwen-vl-max (128K token context)
@@ -187,8 +188,8 @@ const OUTPUT_PATTERNS: Array<[RegExp, TokenCount]> = [
// Generic vision-model: same as qwen-vl-max-latest (8K max output tokens)
[/^vision-model$/, LIMITS['8k']],
// Qwen3-VL-Plus: 8,192 max output tokens
[/^qwen3-vl-plus$/, LIMITS['8k']],
// Qwen3-VL-Plus: 32K max output tokens
[/^qwen3-vl-plus$/, LIMITS['32k']],
];
/**

View File

@@ -1,6 +1,6 @@
{
"name": "@qwen-code/qwen-code-test-utils",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"private": true,
"main": "src/index.ts",
"license": "Apache-2.0",

View File

@@ -2,7 +2,7 @@
"name": "qwen-code-vscode-ide-companion",
"displayName": "Qwen Code Companion",
"description": "Enable Qwen Code with direct access to your VS Code workspace.",
"version": "0.0.14-nightly.1",
"version": "0.0.14-nightly.2",
"publisher": "qwenlm",
"icon": "assets/icon.png",
"repository": {