feat(llm,tool/image): dashscope-compat provider + media-gen test profile

This commit is contained in:
matevip 2026-05-09 06:28:38 +08:00
parent 3f289da6b7
commit 52e06afec4
11 changed files with 209 additions and 16 deletions

View File

@ -623,5 +623,27 @@
</pluginRepository>
</pluginRepositories>
</profile>
<!--
Profile: focused test run for image / video generation features.
Activate with `mvn test -P media-gen` (or `mvn verify -P media-gen`).
Limits surefire to JUnit 5 tests carrying @Tag("media-gen") so the
full ~50-min suite is skipped when iterating on this surface.
Add a tag to a new test with @Tag("media-gen") to opt it in.
-->
<profile>
<id>media-gen</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<groups>media-gen</groups>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -14,9 +14,10 @@ import java.util.Set;
*
* <p>Two transport families are present:
* <ul>
* <li><b>Async legacy</b> ({@link #LEGACY_ASYNC_ENDPOINT}) wanx 2.0/2.1 and
* wan 2.2/2.5 turbo/plus models that exclusively do text-to-image. The
* caller submits and polls {@code /api/v1/tasks/{id}}.</li>
* <li><b>Async legacy</b> ({@link #LEGACY_ASYNC_ENDPOINT}
* {@code text2image/image-synthesis}) wanx 2.0/2.1 and wan 2.2/2.5
* turbo/plus models that exclusively do text-to-image. The caller
* submits and polls {@code /api/v1/tasks/{id}}.</li>
* <li><b>Sync multimodal</b> ({@link #MULTIMODAL_ENDPOINT}) wan 2.6/2.7,
* qwen-image, qwen-image-edit, z-image. Uses the OpenAI-style
* {@code messages.content[]} array and returns the generated image URL
@ -27,8 +28,15 @@ import java.util.Set;
*/
final class DashScopeImageModels {
/**
* Async text-to-image endpoint for the wanx 2.0/2.1 + wan 2.2/2.5 turbo/plus
* families. Despite Aliyun's docs occasionally describing a unified
* {@code image-generation/generation} path, the wanx-series turbo/plus
* models actually still go through {@code text2image/image-synthesis} and
* return {@code "url error, please check url"} on the other path.
*/
static final String LEGACY_ASYNC_ENDPOINT =
"https://dashscope.aliyuncs.com/api/v1/services/aigc/image-generation/generation";
"https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis";
static final String MULTIMODAL_ENDPOINT =
"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation";
static final String TASKS_ENDPOINT_PREFIX =

View File

@ -30,7 +30,7 @@ import java.util.Set;
* DashScope image provider routes per-model between two transports:
*
* <ul>
* <li><b>Async legacy</b> ({@code services/aigc/image-generation/generation})
* <li><b>Async legacy</b> ({@code services/aigc/text2image/image-synthesis})
* for the wanx 2.0/2.1, wan 2.2/2.5 turbo/plus families. Submit returns a
* task id; the caller polls {@code /api/v1/tasks/{id}} until
* SUCCEEDED.</li>
@ -174,8 +174,11 @@ public class DashScopeImageProvider implements ImageGenerationProvider {
* editing but names a model that doesn't support edits (or names nothing),
* fall back to {@link DashScopeImageModels#DEFAULT_EDIT_MODEL} so the call
* doesn't silently degrade to a text-only generation.
*
* <p>Package-private for direct testing of the routing decision (the
* surrounding submit() goes over HTTP and is not a unit-test surface).
*/
private ImageModelSpec resolveSpec(ImageGenerationRequest request) {
ImageModelSpec resolveSpec(ImageGenerationRequest request) {
boolean wantsEdit = request.getInputImages() != null && !request.getInputImages().isEmpty();
String requested = request.getModel();
ImageModelSpec spec = DashScopeImageModels.get(requested);

View File

@ -60,14 +60,16 @@ public class DashScopeVideoProvider implements VideoGenerationProvider {
private static final String DEFAULT_T2V_MODEL = "wan2.5-t2v-turbo";
private static final String DEFAULT_I2V_MODEL = "wan2.5-i2v-turbo";
private enum BodyShape {
/** Package-private so per-routing tests can switch on it without reflection. */
enum BodyShape {
/** input.img_url + parameters.size("1280*720") + parameters.duration. */
LEGACY,
/** input.media[].first_frame + parameters.resolution + parameters.ratio + parameters.duration. */
UNIFIED
}
private record ModelSpec(
/** Package-private for unit tests; the MODELS map is the routing source of truth. */
record ModelSpec(
String id,
String endpoint,
BodyShape bodyShape,
@ -213,7 +215,8 @@ public class DashScopeVideoProvider implements VideoGenerationProvider {
// ==================== spec resolution ====================
private ModelSpec resolveSpec(VideoGenerationRequest request) {
/** Package-private for direct unit tests — submit() goes over HTTP and is not a unit-test surface. */
ModelSpec resolveSpec(VideoGenerationRequest request) {
String requested = request.getModel();
if (requested != null && !requested.isBlank() && MODELS.containsKey(requested)) {
return MODELS.get(requested);
@ -226,7 +229,8 @@ public class DashScopeVideoProvider implements VideoGenerationProvider {
// ==================== body building ====================
private ObjectNode buildRequestBody(VideoGenerationRequest request, ModelSpec spec) {
/** Package-private for unit tests; verify the JSON shape per body family without HTTP. */
ObjectNode buildRequestBody(VideoGenerationRequest request, ModelSpec spec) {
return switch (spec.bodyShape()) {
case LEGACY -> buildLegacyBody(request, spec);
case UNIFIED -> buildUnifiedBody(request, spec);

View File

@ -50,6 +50,13 @@ MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, a
KEY (provider_id)
VALUES ('dashscope', 'DashScope', 'sk-', 'DashScopeChatModel', '', '', '{}', FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, NOW(), NOW());
-- DashScope OpenAI-compatible endpoint: shares the same sk- key as the
-- dashscope provider but routes to compatible-mode/v1. Dot-versioned qwen
-- families (qwen3.5-*, qwen3.6-*) are only callable here.
MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
KEY (provider_id)
VALUES ('dashscope-compat', 'DashScope (OpenAI-compatible)', 'sk-', 'OpenAIChatModel', '', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW());
MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
KEY (provider_id)
VALUES ('modelscope', 'ModelScope', 'ms', 'OpenAIChatModel', '', 'https://api-inference.modelscope.cn/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW());
@ -185,11 +192,18 @@ MERGE INTO mate_model_config (id, name, provider, model_name, description, tempe
(1000000103, 'DeepSeek-V3.2', 'dashscope', 'deepseek-v3.2', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- Note: dotted Qwen3 versions (qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-*) only ship on the
-- OpenAI-compatible endpoint. Calling them through DashScope native (text-generation/generation)
-- returns 400 InvalidParameter — use the bailian-team OpenAI-compat provider instead.
-- returns 400 InvalidParameter. They are registered under the dashscope-compat provider, which shares
-- the same sk- key but routes to compatible-mode/v1.
(1000000173, 'Qwen Long', 'dashscope', 'qwen-long', 'Long-context model with extended context support', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000174, 'Qwen Plus (latest)', 'dashscope', 'qwen-plus-latest', 'Latest stable snapshot of Qwen Plus — auto-updates as Bailian rolls new releases', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000175, 'Qwen Max (latest)', 'dashscope', 'qwen-max-latest', 'Latest stable snapshot of Qwen Max — strongest reasoning capability', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000176, 'Qwen Turbo (latest)', 'dashscope', 'qwen-turbo-latest', 'Latest stable snapshot of Qwen Turbo — low latency, high frequency', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- DashScope OpenAI-compat exclusive models (dot-versioned families) — share the same sk- key.
-- Only the -plus variants are seeded; -max / -vl-max are visible in the model market but return
-- 404 for general accounts. Users on a whitelist can add them via Settings → Models manually.
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', 'Qwen3.6 Plus flagship — balanced reasoning and speed (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', 'Qwen3.5 Plus (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', 'Qwen3 vision-language Plus — accepts image / video input (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000104, 'Qwen3.5-122B-A10B', 'modelscope', 'Qwen/Qwen3.5-122B-A10B', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000105, 'GLM-5', 'modelscope', 'ZhipuAI/GLM-5', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000106, 'Qwen3.5 Plus', 'aliyun-codingplan', 'qwen3.5-plus', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),

View File

@ -50,6 +50,14 @@ INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model,
VALUES ('dashscope', 'DashScope', 'sk-', 'DashScopeChatModel', '', '', '{}', FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
-- DashScope OpenAI-compatible endpoint: shares the same sk- key as the
-- dashscope provider but routes to compatible-mode/v1. Dot-versioned qwen
-- families (qwen3.5-*, qwen3.6-*) are only callable here; the native endpoint
-- returns 400 InvalidParameter for them.
INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
VALUES ('dashscope-compat', 'DashScope (OpenAI-compatible)', 'sk-', 'OpenAIChatModel', '', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
VALUES ('modelscope', 'ModelScope', 'ms', 'OpenAIChatModel', '', 'https://api-inference.modelscope.cn/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
@ -200,11 +208,18 @@ VALUES
(1000000103, 'DeepSeek-V3.2', 'dashscope', 'deepseek-v3.2', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- Note: dotted Qwen3 versions (qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-*) only ship on the
-- OpenAI-compatible endpoint. Calling them through DashScope native (text-generation/generation)
-- returns 400 InvalidParameter — use the bailian-team OpenAI-compat provider instead.
-- returns 400 InvalidParameter. They are registered under the dashscope-compat provider, which shares
-- the same sk- key but routes to compatible-mode/v1.
(1000000173, 'Qwen Long', 'dashscope', 'qwen-long', 'Long-context model with extended context support', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000174, 'Qwen Plus (latest)', 'dashscope', 'qwen-plus-latest', 'Latest stable snapshot of Qwen Plus — auto-updates as Bailian rolls new releases', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000175, 'Qwen Max (latest)', 'dashscope', 'qwen-max-latest', 'Latest stable snapshot of Qwen Max — strongest reasoning capability', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000176, 'Qwen Turbo (latest)', 'dashscope', 'qwen-turbo-latest', 'Latest stable snapshot of Qwen Turbo — low latency, high frequency', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- DashScope OpenAI-compat exclusive models (dot-versioned families) — share the same sk- key.
-- Only the -plus variants are seeded; -max / -vl-max are visible in the model market but return
-- 404 for general accounts. Users on a whitelist can add them via Settings → Models manually.
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', 'Qwen3.6 Plus flagship — balanced reasoning and speed (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', 'Qwen3.5 Plus (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', 'Qwen3 vision-language Plus — accepts image / video input (compat-mode only)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000104, 'Qwen3.5-122B-A10B', 'modelscope', 'Qwen/Qwen3.5-122B-A10B', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000105, 'GLM-5', 'modelscope', 'ZhipuAI/GLM-5', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000106, 'Qwen3.5 Plus', 'aliyun-codingplan', 'qwen3.5-plus', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),

View File

@ -50,6 +50,13 @@ INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model,
VALUES ('dashscope', 'DashScope', 'sk-', 'DashScopeChatModel', '', '', '{}', FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
-- DashScope OpenAI 兼容端点:与 dashscope provider 共用同一把 sk- key但走
-- compatible-mode/v1 路径。带点号版本号的 qwen 系列qwen3.5-*, qwen3.6-*)只在
-- 这里能调通——native 端点会返回 400 InvalidParameter。
INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
VALUES ('dashscope-compat', 'DashScope (兼容模式)', 'sk-', 'OpenAIChatModel', '', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
VALUES ('modelscope', 'ModelScope', 'ms', 'OpenAIChatModel', '', 'https://api-inference.modelscope.cn/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW())
ON DUPLICATE KEY UPDATE name=VALUES(name), api_key_prefix=VALUES(api_key_prefix), chat_model=VALUES(chat_model), api_key=VALUES(api_key), base_url=VALUES(base_url), generate_kwargs=VALUES(generate_kwargs), is_custom=VALUES(is_custom), is_local=VALUES(is_local), support_model_discovery=VALUES(support_model_discovery), support_connection_check=VALUES(support_connection_check), freeze_url=VALUES(freeze_url), require_api_key=VALUES(require_api_key), update_time=VALUES(update_time);
@ -198,12 +205,18 @@ VALUES
(1000000101, 'Qwen3 Max', 'dashscope', 'qwen3-max', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000102, 'Qwen3 235B A22B Thinking', 'dashscope', 'qwen3-235b-a22b-thinking-2507', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000103, 'DeepSeek-V3.2', 'dashscope', 'deepseek-v3.2', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- 注意: qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-* 等带点号的版本只在 OpenAI 兼容端点上线,
-- DashScope nativetext-generation/generation调用会返回 400 InvalidParameter请使用 bailian-team 等 OpenAI-compat provider。
-- 注意: qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-* 等带点号的版本只在 OpenAI 兼容端点上线。
-- DashScope nativetext-generation/generation调用会返回 400 InvalidParameter。
-- 这些模型挂在 dashscope-compat provider 下,复用同一把 sk- key 但走 compatible-mode/v1 端点。
(1000000173, 'Qwen Long', 'dashscope', 'qwen-long', '长文本模型,支持超长上下文', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000174, 'Qwen Plus (latest)', 'dashscope', 'qwen-plus-latest', '通义千问 Plus 最新稳定快照,自动跟随官方更新', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000175, 'Qwen Max (latest)', 'dashscope', 'qwen-max-latest', '通义千问 Max 最新稳定快照,最强推理能力', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000176, 'Qwen Turbo (latest)', 'dashscope', 'qwen-turbo-latest', '通义千问 Turbo 最新稳定快照,低延迟、高并发', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- DashScope 兼容模式专属模型(点号版本号系列)—— 与 dashscope provider 共用同一把 sk- key。
-- 仅收录在通用账号上确实可调通的 -plus 版本;-max / -vl-max 在 model market 可见但 API 返回 404。
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', '通义千问 3.6 Plus 旗舰,平衡推理与速度(兼容模式专属)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', '通义千问 3.5 Plus兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', '通义千问 3 视觉理解 Plus支持图像、视频输入兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000104, 'Qwen3.5-122B-A10B', 'modelscope', 'Qwen/Qwen3.5-122B-A10B', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000105, 'GLM-5', 'modelscope', 'ZhipuAI/GLM-5', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000106, 'Qwen3.5 Plus', 'aliyun-codingplan', 'qwen3.5-plus', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),

View File

@ -50,6 +50,13 @@ MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, a
KEY (provider_id)
VALUES ('dashscope', 'DashScope', 'sk-', 'DashScopeChatModel', '', '', '{}', FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, NOW(), NOW());
-- DashScope OpenAI 兼容端点:与 dashscope provider 共用同一把 sk- key但走
-- compatible-mode/v1 路径。带点号版本号的 qwen 系列qwen3.5-*, qwen3.6-*)只在
-- 这里能调通——native 端点会返回 400 InvalidParameter。
MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
KEY (provider_id)
VALUES ('dashscope-compat', 'DashScope (兼容模式)', 'sk-', 'OpenAIChatModel', '', 'https://dashscope.aliyuncs.com/compatible-mode/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW());
MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
KEY (provider_id)
VALUES ('modelscope', 'ModelScope', 'ms', 'OpenAIChatModel', '', 'https://api-inference.modelscope.cn/v1', '{}', FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, NOW(), NOW());
@ -187,12 +194,18 @@ MERGE INTO mate_model_config (id, name, provider, model_name, description, tempe
(1000000101, 'Qwen3 Max', 'dashscope', 'qwen3-max', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000102, 'Qwen3 235B A22B Thinking', 'dashscope', 'qwen3-235b-a22b-thinking-2507', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000103, 'DeepSeek-V3.2', 'dashscope', 'deepseek-v3.2', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- 注意: qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-* 等带点号的版本只在 OpenAI 兼容端点上线,
-- DashScope nativetext-generation/generation调用会返回 400 InvalidParameter请使用 bailian-team 等 OpenAI-compat provider。
-- 注意: qwen3-plus / qwen3.5-plus / qwen3.5-max / qwen3.6-* 等带点号的版本只在 OpenAI 兼容端点上线。
-- DashScope nativetext-generation/generation调用会返回 400 InvalidParameter。
-- 这些模型挂在 dashscope-compat provider 下,复用同一把 sk- key 但走 compatible-mode/v1 端点。
(1000000173, 'Qwen Long', 'dashscope', 'qwen-long', '长文本模型,支持超长上下文', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000174, 'Qwen Plus (latest)', 'dashscope', 'qwen-plus-latest', '通义千问 Plus 最新稳定快照,自动跟随官方更新', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000175, 'Qwen Max (latest)', 'dashscope', 'qwen-max-latest', '通义千问 Max 最新稳定快照,最强推理能力', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000176, 'Qwen Turbo (latest)', 'dashscope', 'qwen-turbo-latest', '通义千问 Turbo 最新稳定快照,低延迟、高并发', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
-- DashScope 兼容模式专属模型(点号版本号系列)—— 与 dashscope provider 共用同一把 sk- key。
-- 仅收录在通用账号上确实可调通的 -plus 版本;-max / -vl-max 在 model market 可见但 API 返回 404。
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', '通义千问 3.6 Plus 旗舰,平衡推理与速度(兼容模式专属)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', '通义千问 3.5 Plus兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', '通义千问 3 视觉理解 Plus支持图像、视频输入兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000104, 'Qwen3.5-122B-A10B', 'modelscope', 'Qwen/Qwen3.5-122B-A10B', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000105, 'GLM-5', 'modelscope', 'ZhipuAI/GLM-5', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000106, 'Qwen3.5 Plus', 'aliyun-codingplan', 'qwen3.5-plus', '', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),

View File

@ -0,0 +1,48 @@
-- V99: register a DashScope OpenAI-compatible provider entry alongside the
-- existing native dashscope provider, plus the dot-versioned Qwen families
-- (qwen3.5-*, qwen3.6-*) that only ship on compatible-mode/v1.
--
-- Why a separate provider:
-- The dashscope provider runs on DashScopeChatModel (native protocol). Calling
-- a dot-versioned model id through the native text-generation/generation
-- endpoint returns 400 InvalidParameter — those models are only exposed via
-- the OpenAI-compatible endpoint. Rather than dynamically rewriting the
-- protocol per model, we register a sibling provider that uses
-- OpenAIChatModel against compatible-mode/v1 with the same sk- API key.
--
-- Existing seed file db/data-zh.sql already carries the same rows for fresh
-- installs; this migration is the upgrade path for already-deployed databases
-- (DatabaseBootstrapRunner skips the seed when mate_user is non-empty).
-- -- Provider --------------------------------------------------------------
MERGE INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
KEY (provider_id)
VALUES (
'dashscope-compat',
'DashScope (兼容模式)',
'sk-',
'OpenAIChatModel',
'',
'https://dashscope.aliyuncs.com/compatible-mode/v1',
'{}',
FALSE, FALSE, TRUE, TRUE, TRUE, TRUE,
NOW(), NOW()
);
-- -- Model catalog ---------------------------------------------------------
-- Dot-versioned Qwen families exposed through compatible-mode. IDs use the
-- 1000000601-1000000606 block reserved for this provider so future additions
-- under dashscope-compat can grow contiguously.
--
-- NB: only the {-plus, -vl-plus} variants are public on compatible-mode at the
-- time this migration was written. The {-max, -vl-max} variants exist in the
-- model marketplace but return 404 (`The model 'qwen3.6-max' does not exist
-- or you do not have access to it.`) for all general accounts. We seed only
-- the verified-callable ones; users with whitelist access can add the others
-- through Settings → Models manually.
MERGE INTO mate_model_config (id, name, provider, model_name, description, temperature, max_tokens, top_p, builtin, enabled, is_default, create_time, update_time, deleted)
KEY (id)
VALUES
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', '通义千问 3.6 Plus 旗舰,平衡推理与速度(兼容模式专属)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', '通义千问 3.5 Plus兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', '通义千问 3 视觉理解 Plus支持图像、视频输入兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0);

View File

@ -0,0 +1,51 @@
-- V99: register a DashScope OpenAI-compatible provider entry alongside the
-- existing native dashscope provider, plus the dot-versioned Qwen families
-- (qwen3.5-*, qwen3.6-*) that only ship on compatible-mode/v1.
--
-- See the H2 copy for full background. The MySQL copy uses INSERT ... ON
-- DUPLICATE KEY UPDATE; the api_key column is intentionally omitted from the
-- update list so existing deployments that have already configured a key keep
-- it (this only matters if a future migration re-applies a similar block;
-- Flyway runs each version once today).
-- -- Provider --------------------------------------------------------------
INSERT INTO mate_model_provider (provider_id, name, api_key_prefix, chat_model, api_key, base_url, generate_kwargs, is_custom, is_local, support_model_discovery, support_connection_check, freeze_url, require_api_key, create_time, update_time)
VALUES (
'dashscope-compat',
'DashScope (兼容模式)',
'sk-',
'OpenAIChatModel',
'',
'https://dashscope.aliyuncs.com/compatible-mode/v1',
'{}',
FALSE, FALSE, TRUE, TRUE, TRUE, TRUE,
NOW(), NOW()
)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
api_key_prefix = VALUES(api_key_prefix),
chat_model = VALUES(chat_model),
base_url = VALUES(base_url),
generate_kwargs = VALUES(generate_kwargs),
support_model_discovery = VALUES(support_model_discovery),
support_connection_check = VALUES(support_connection_check),
freeze_url = VALUES(freeze_url),
require_api_key = VALUES(require_api_key),
update_time = VALUES(update_time);
-- -- Model catalog ---------------------------------------------------------
-- Only seed the variants that are publicly callable on compatible-mode. The
-- -max / -vl-max variants exist in the marketplace but return 404 for general
-- accounts; users with whitelist access can add them via Settings → Models.
INSERT INTO mate_model_config (id, name, provider, model_name, description, temperature, max_tokens, top_p, builtin, enabled, is_default, create_time, update_time, deleted)
VALUES
(1000000601, 'Qwen3.6 Plus', 'dashscope-compat', 'qwen3.6-plus', '通义千问 3.6 Plus 旗舰,平衡推理与速度(兼容模式专属)', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000603, 'Qwen3.5 Plus', 'dashscope-compat', 'qwen3.5-plus', '通义千问 3.5 Plus兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0),
(1000000605, 'Qwen3 VL Plus', 'dashscope-compat', 'qwen3-vl-plus', '通义千问 3 视觉理解 Plus支持图像、视频输入兼容模式专属', 0.7, 4096, 0.8, TRUE, TRUE, FALSE, NOW(), NOW(), 0)
ON DUPLICATE KEY UPDATE
name = VALUES(name),
model_name = VALUES(model_name),
description = VALUES(description),
builtin = VALUES(builtin),
enabled = VALUES(enabled),
update_time = VALUES(update_time);

View File

@ -72,6 +72,8 @@ export function useProviderList() {
const providerIconMap: Record<string, string> = {
'dashscope': '/icons/providers/dashscope.png',
// dashscope-compat shares the same Aliyun DashScope brand — same logo.
'dashscope-compat': '/icons/providers/dashscope.png',
'modelscope': '/icons/providers/modelscope.svg',
'aliyun-codingplan': '/icons/providers/aliyun-codingplan.svg',
'aliyun-codingplan-intl': '/icons/providers/aliyun-codingplan.svg',