Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
<name>DashScope Java SDK</name>
<groupId>com.alibaba</groupId>
<artifactId>dashscope-sdk-java</artifactId>
<version>2.23.0</version>
<version>2.23.1</version>

<properties>
<maven.compiler.source>8</maven.compiler.source>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/alibaba/dashscope/Version.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@
package com.alibaba.dashscope;

public final class Version {
public static final String version = "2.23.0";
public static final String version = "2.23.1";
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import com.alibaba.dashscope.utils.JsonUtils;
import com.google.gson.JsonObject;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import lombok.experimental.SuperBuilder;
Expand All @@ -18,17 +20,75 @@
public class MultiModalEmbeddingParam extends HalfDuplexServiceParam {
@NonNull private List<MultiModalEmbeddingItemBase> contents;

/**
* The output vector dimensions. Supported values vary by model. For example,
* multimodal-embedding-v1 outputs 1024-dimension vectors only and ignores this parameter, while
* tongyi-embedding-vision-plus supports multiple dimensions (1152 by default).
*/
private Integer dimension;

/** The output vector format. Currently only "dense" is supported. */
private String outputType;

/** The video frame extraction ratio, in range [0, 1]. Default: 1.0. */
private Double fps;

/** Custom task instruction to guide model understanding of query intent. */
private String instruct;

/**
* Only applicable to qwen3-vl-embedding. When true, all contents are fused into a single vector.
*/
private Boolean enableFusion;

/** The resolution level of the input images/videos. */
private Integer resLevel;

/** The maximum number of frames extracted from the input video. */
private Integer maxVideoFrames;

public List<MultiModalEmbeddingItemBase> getContent() {
return contents;
}

@Override
public Map<String, Object> getParameters() {
Map<String, Object> params = new HashMap<>();
if (dimension != null) {
params.put("dimension", dimension);
}
if (outputType != null) {
params.put("output_type", outputType);
}
if (fps != null) {
params.put("fps", fps);
}
if (instruct != null) {
params.put("instruct", instruct);
}
if (enableFusion != null) {
params.put("enable_fusion", enableFusion);
}
if (resLevel != null) {
params.put("res_level", resLevel);
}
if (maxVideoFrames != null) {
params.put("max_video_frames", maxVideoFrames);
}
if (parameters != null && !parameters.isEmpty()) {
params.putAll(parameters);
}
return params;
}

@Override
public JsonObject getHttpBody() {
JsonObject requestObject = new JsonObject();
requestObject.addProperty(ApiKeywords.MODEL, getModel());
requestObject.add(ApiKeywords.INPUT, getInput());
if (parameters != null && !parameters.isEmpty()) {
requestObject.add(ApiKeywords.PARAMETERS, JsonUtils.parametersToJsonObject(getParameters()));
Map<String, Object> params = getParameters();
if (params != null && !params.isEmpty()) {
requestObject.add(ApiKeywords.PARAMETERS, JsonUtils.parametersToJsonObject(params));
}
return requestObject;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.alibaba.dashscope;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import com.alibaba.dashscope.embeddings.MultiModalEmbeddingItemImage;
import com.alibaba.dashscope.embeddings.MultiModalEmbeddingItemText;
import com.alibaba.dashscope.embeddings.MultiModalEmbeddingParam;
import com.google.gson.JsonObject;
import java.util.Arrays;
import org.junit.jupiter.api.Test;

public class TestMultiModalEmbeddingParam {

private MultiModalEmbeddingParam.MultiModalEmbeddingParamBuilder<?, ?> baseBuilder() {
return MultiModalEmbeddingParam.builder()
.model("tongyi-embedding-vision-plus")
.apiKey("test-key")
.contents(
Arrays.asList(
new MultiModalEmbeddingItemImage("https://example.com/a.jpg"),
new MultiModalEmbeddingItemText("hello")));
}

@Test
public void testDimensionSerializedIntoParameters() {
MultiModalEmbeddingParam param = baseBuilder().dimension(1152).build();
JsonObject body = param.getHttpBody();
assertTrue(body.has("parameters"));
assertEquals(1152, body.getAsJsonObject("parameters").get("dimension").getAsInt());
}

@Test
public void testAllExplicitParamsSerialized() {
MultiModalEmbeddingParam param =
baseBuilder()
.dimension(1024)
.outputType("dense")
.fps(0.5)
.instruct("retrieve images")
.enableFusion(true)
.resLevel(1)
.maxVideoFrames(16)
.build();
JsonObject params = param.getHttpBody().getAsJsonObject("parameters");
assertEquals(1024, params.get("dimension").getAsInt());
assertEquals("dense", params.get("output_type").getAsString());
assertEquals(0.5, params.get("fps").getAsDouble(), 1e-9);
assertEquals("retrieve images", params.get("instruct").getAsString());
assertTrue(params.get("enable_fusion").getAsBoolean());
assertEquals(1, params.get("res_level").getAsInt());
assertEquals(16, params.get("max_video_frames").getAsInt());
}

@Test
public void testGenericParameterStillWorks() {
// 旧用法:通用 parameters 通道
MultiModalEmbeddingParam param = baseBuilder().parameter("dimension", 768).build();
JsonObject params = param.getHttpBody().getAsJsonObject("parameters");
assertEquals(768, params.get("dimension").getAsInt());
}

@Test
public void testNoExplicitParamsNoDimensionKey() {
MultiModalEmbeddingParam param = baseBuilder().build();
JsonObject body = param.getHttpBody();
if (body.has("parameters")) {
assertFalse(body.getAsJsonObject("parameters").has("dimension"));
}
// contents 始终在 input 中
assertEquals(2, body.getAsJsonObject("input").getAsJsonArray("contents").size());
}
}
Loading