Skip to content

Commit 9db8553

Browse files
lzswebzhansheng.lzsluk384090-cloud
authored
feat: add explicit dimension and other params to MultiModalEmbeddingParam (#273)
* feat: add explicit dimension and other params to MultiModalEmbeddingParam Align MultiModalEmbeddingParam with Python SDK by exposing dimension, output_type, fps, instruct, enable_fusion, res_level and max_video_frames as explicit builder fields. Generic .parameter() channel still takes precedence for backward compatibility. Add unit tests for serialization. * chore(version): update version from 2.23.0 to 2.23.1 - 更新 pom.xml 中的版本号 - 更新 Version.java 中的版本号 --------- Co-authored-by: zhansheng.lzs <zhansheng.lzs@alibaba-inc.com> Co-authored-by: luk384090-cloud <lu384090@gmail.com>
1 parent a777b63 commit 9db8553

4 files changed

Lines changed: 138 additions & 4 deletions

File tree

‎pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
<name>DashScope Java SDK</name>
4141
<groupId>com.alibaba</groupId>
4242
<artifactId>dashscope-sdk-java</artifactId>
43-
<version>2.23.0</version>
43+
<version>2.23.1</version>
4444

4545
<properties>
4646
<maven.compiler.source>8</maven.compiler.source>

‎src/main/java/com/alibaba/dashscope/Version.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
package com.alibaba.dashscope;
44

55
public final class Version {
6-
public static final String version = "2.23.0";
6+
public static final String version = "2.23.1";
77
}

‎src/main/java/com/alibaba/dashscope/embeddings/MultiModalEmbeddingParam.java‎

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
import com.alibaba.dashscope.utils.JsonUtils;
99
import com.google.gson.JsonObject;
1010
import java.nio.ByteBuffer;
11+
import java.util.HashMap;
1112
import java.util.List;
13+
import java.util.Map;
1214
import lombok.EqualsAndHashCode;
1315
import lombok.NonNull;
1416
import lombok.experimental.SuperBuilder;
@@ -18,17 +20,75 @@
1820
public class MultiModalEmbeddingParam extends HalfDuplexServiceParam {
1921
@NonNull private List<MultiModalEmbeddingItemBase> contents;
2022

23+
/**
24+
* The output vector dimensions. Supported values vary by model. For example,
25+
* multimodal-embedding-v1 outputs 1024-dimension vectors only and ignores this parameter, while
26+
* tongyi-embedding-vision-plus supports multiple dimensions (1152 by default).
27+
*/
28+
private Integer dimension;
29+
30+
/** The output vector format. Currently only "dense" is supported. */
31+
private String outputType;
32+
33+
/** The video frame extraction ratio, in range [0, 1]. Default: 1.0. */
34+
private Double fps;
35+
36+
/** Custom task instruction to guide model understanding of query intent. */
37+
private String instruct;
38+
39+
/**
40+
* Only applicable to qwen3-vl-embedding. When true, all contents are fused into a single vector.
41+
*/
42+
private Boolean enableFusion;
43+
44+
/** The resolution level of the input images/videos. */
45+
private Integer resLevel;
46+
47+
/** The maximum number of frames extracted from the input video. */
48+
private Integer maxVideoFrames;
49+
2150
public List<MultiModalEmbeddingItemBase> getContent() {
2251
return contents;
2352
}
2453

54+
@Override
55+
public Map<String, Object> getParameters() {
56+
Map<String, Object> params = new HashMap<>();
57+
if (dimension != null) {
58+
params.put("dimension", dimension);
59+
}
60+
if (outputType != null) {
61+
params.put("output_type", outputType);
62+
}
63+
if (fps != null) {
64+
params.put("fps", fps);
65+
}
66+
if (instruct != null) {
67+
params.put("instruct", instruct);
68+
}
69+
if (enableFusion != null) {
70+
params.put("enable_fusion", enableFusion);
71+
}
72+
if (resLevel != null) {
73+
params.put("res_level", resLevel);
74+
}
75+
if (maxVideoFrames != null) {
76+
params.put("max_video_frames", maxVideoFrames);
77+
}
78+
if (parameters != null && !parameters.isEmpty()) {
79+
params.putAll(parameters);
80+
}
81+
return params;
82+
}
83+
2584
@Override
2685
public JsonObject getHttpBody() {
2786
JsonObject requestObject = new JsonObject();
2887
requestObject.addProperty(ApiKeywords.MODEL, getModel());
2988
requestObject.add(ApiKeywords.INPUT, getInput());
30-
if (parameters != null && !parameters.isEmpty()) {
31-
requestObject.add(ApiKeywords.PARAMETERS, JsonUtils.parametersToJsonObject(getParameters()));
89+
Map<String, Object> params = getParameters();
90+
if (params != null && !params.isEmpty()) {
91+
requestObject.add(ApiKeywords.PARAMETERS, JsonUtils.parametersToJsonObject(params));
3292
}
3393
return requestObject;
3494
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.alibaba.dashscope;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertFalse;
5+
import static org.junit.Assert.assertTrue;
6+
7+
import com.alibaba.dashscope.embeddings.MultiModalEmbeddingItemImage;
8+
import com.alibaba.dashscope.embeddings.MultiModalEmbeddingItemText;
9+
import com.alibaba.dashscope.embeddings.MultiModalEmbeddingParam;
10+
import com.google.gson.JsonObject;
11+
import java.util.Arrays;
12+
import org.junit.jupiter.api.Test;
13+
14+
public class TestMultiModalEmbeddingParam {
15+
16+
private MultiModalEmbeddingParam.MultiModalEmbeddingParamBuilder<?, ?> baseBuilder() {
17+
return MultiModalEmbeddingParam.builder()
18+
.model("tongyi-embedding-vision-plus")
19+
.apiKey("test-key")
20+
.contents(
21+
Arrays.asList(
22+
new MultiModalEmbeddingItemImage("https://example.com/a.jpg"),
23+
new MultiModalEmbeddingItemText("hello")));
24+
}
25+
26+
@Test
27+
public void testDimensionSerializedIntoParameters() {
28+
MultiModalEmbeddingParam param = baseBuilder().dimension(1152).build();
29+
JsonObject body = param.getHttpBody();
30+
assertTrue(body.has("parameters"));
31+
assertEquals(1152, body.getAsJsonObject("parameters").get("dimension").getAsInt());
32+
}
33+
34+
@Test
35+
public void testAllExplicitParamsSerialized() {
36+
MultiModalEmbeddingParam param =
37+
baseBuilder()
38+
.dimension(1024)
39+
.outputType("dense")
40+
.fps(0.5)
41+
.instruct("retrieve images")
42+
.enableFusion(true)
43+
.resLevel(1)
44+
.maxVideoFrames(16)
45+
.build();
46+
JsonObject params = param.getHttpBody().getAsJsonObject("parameters");
47+
assertEquals(1024, params.get("dimension").getAsInt());
48+
assertEquals("dense", params.get("output_type").getAsString());
49+
assertEquals(0.5, params.get("fps").getAsDouble(), 1e-9);
50+
assertEquals("retrieve images", params.get("instruct").getAsString());
51+
assertTrue(params.get("enable_fusion").getAsBoolean());
52+
assertEquals(1, params.get("res_level").getAsInt());
53+
assertEquals(16, params.get("max_video_frames").getAsInt());
54+
}
55+
56+
@Test
57+
public void testGenericParameterStillWorks() {
58+
// 旧用法:通用 parameters 通道
59+
MultiModalEmbeddingParam param = baseBuilder().parameter("dimension", 768).build();
60+
JsonObject params = param.getHttpBody().getAsJsonObject("parameters");
61+
assertEquals(768, params.get("dimension").getAsInt());
62+
}
63+
64+
@Test
65+
public void testNoExplicitParamsNoDimensionKey() {
66+
MultiModalEmbeddingParam param = baseBuilder().build();
67+
JsonObject body = param.getHttpBody();
68+
if (body.has("parameters")) {
69+
assertFalse(body.getAsJsonObject("parameters").has("dimension"));
70+
}
71+
// contents 始终在 input 中
72+
assertEquals(2, body.getAsJsonObject("input").getAsJsonArray("contents").size());
73+
}
74+
}

0 commit comments

Comments
 (0)