diff --git a/src/main/java/com/alibaba/dashscope/api/AsynchronousApi.java b/src/main/java/com/alibaba/dashscope/api/AsynchronousApi.java index 5698aa7..ca7e03d 100644 --- a/src/main/java/com/alibaba/dashscope/api/AsynchronousApi.java +++ b/src/main/java/com/alibaba/dashscope/api/AsynchronousApi.java @@ -6,6 +6,7 @@ import com.alibaba.dashscope.base.HalfDuplexParamBase; import com.alibaba.dashscope.common.DashScopeResult; +import com.alibaba.dashscope.common.Status; import com.alibaba.dashscope.common.TaskStatus; import com.alibaba.dashscope.exception.ApiException; import com.alibaba.dashscope.exception.NoApiKeyException; @@ -76,12 +77,17 @@ public DashScopeResult asyncCall(ParamT param, ServiceOption serviceOption) * @param apiKey The api-key. * @param baseUrl The base http url. * @param customHeaders The custom headers. + * @param timeoutSeconds The maximum time to wait in seconds. * @return The task result. * @throws NoApiKeyException Can not find api key - * @throws ApiException The request failed, possibly due to a network or data error. + * @throws ApiException The request failed, possibly due to a network or data error, or timeout. */ public DashScopeResult wait( - String taskId, String apiKey, String baseUrl, Map customHeaders) + String taskId, + String apiKey, + String baseUrl, + Map customHeaders, + long timeoutSeconds) throws ApiException, NoApiKeyException { AsyncTaskOption serviceOption = AsyncTaskOption.builder() @@ -98,7 +104,23 @@ public DashScopeResult wait( int maxWaitMilliseconds = 5 * 1000; int incrementSteps = 3; int step = 0; + long startTime = System.currentTimeMillis(); + long timeoutMillis = timeoutSeconds > 0 ? timeoutSeconds * 1000L : -1L; while (true) { + if (timeoutMillis > 0) { + long elapsed = System.currentTimeMillis() - startTime; + if (elapsed >= timeoutMillis) { + throw new ApiException( + Status.builder() + .statusCode(HttpURLConnection.HTTP_CLIENT_TIMEOUT) + .code("TaskWaitTimeout") + .message( + StringUtils.format( + "Waiting for task [%s] timed out after %d ms (timeoutSeconds=%d).", + taskId, elapsed, timeoutSeconds)) + .build()); + } + } try { DashScopeResult taskResult = client.send(req); JsonObject output = (JsonObject) taskResult.getOutput(); @@ -121,9 +143,20 @@ public DashScopeResult wait( ? maxWaitMilliseconds : waitMilliseconds * 2; } + long sleepMs = waitMilliseconds; + if (timeoutMillis > 0) { + long remaining = timeoutMillis - (System.currentTimeMillis() - startTime); + if (remaining <= 0) { + continue; + } + if (remaining < sleepMs) { + sleepMs = remaining; + } + } try { - Thread.sleep(waitMilliseconds); - } catch (InterruptedException ignored) { + Thread.sleep(sleepMs); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); } } } catch (ApiException e) { @@ -135,6 +168,23 @@ public DashScopeResult wait( } } + /** + * Wait for async task completed and return task result. + * + * @param taskId The async task id. + * @param apiKey The api-key. + * @param baseUrl The base http url. + * @param customHeaders The custom headers. + * @return The task result. + * @throws NoApiKeyException Can not find api key + * @throws ApiException The request failed, possibly due to a network or data error. + */ + public DashScopeResult wait( + String taskId, String apiKey, String baseUrl, Map customHeaders) + throws ApiException, NoApiKeyException { + return wait(taskId, apiKey, baseUrl, customHeaders, -1); + } + /** * Wait for async task completed and return task result. * diff --git a/src/main/java/com/alibaba/dashscope/audio/asr/recognition/Recognition.java b/src/main/java/com/alibaba/dashscope/audio/asr/recognition/Recognition.java index 448abf3..d53610b 100644 --- a/src/main/java/com/alibaba/dashscope/audio/asr/recognition/Recognition.java +++ b/src/main/java/com/alibaba/dashscope/audio/asr/recognition/Recognition.java @@ -85,6 +85,9 @@ public static RecognitionParamWithStream FromRecognitionParam( if (param.getPhraseId() != null && !param.getPhraseId().isEmpty()) { recognitionParamWithStream.setPhraseId(param.getPhraseId()); } + if (param.getInputs() != null && !param.getInputs().isEmpty()) { + recognitionParamWithStream.setInput(param.getInputs()); + } return recognitionParamWithStream; } @@ -103,6 +106,10 @@ public Recognition() { duplexApi = new SynchronizeFullDuplexApi<>(serviceOption); } + public void setWebsocketUrl(String websocketUrl) { + serviceOption.setBaseWebSocketUrl(websocketUrl); + } + public Flowable streamCall( RecognitionParam param, Flowable audioFrame) throws ApiException, NoApiKeyException { diff --git a/src/main/java/com/alibaba/dashscope/audio/asr/recognition/RecognitionParam.java b/src/main/java/com/alibaba/dashscope/audio/asr/recognition/RecognitionParam.java index 8634b61..fd31dd1 100644 --- a/src/main/java/com/alibaba/dashscope/audio/asr/recognition/RecognitionParam.java +++ b/src/main/java/com/alibaba/dashscope/audio/asr/recognition/RecognitionParam.java @@ -32,6 +32,8 @@ public class RecognitionParam extends FullDuplexServiceParam { private String vocabularyId; + private Map input; + @Override public Map getParameters() { Map params = new HashMap<>(); @@ -45,6 +47,11 @@ public Map getParameters() { return params; } + @Override + public Map getInputs() { + return input; + } + @Override public Object getResources() { if (phraseId == null || phraseId.isEmpty()) { diff --git a/src/main/java/com/alibaba/dashscope/audio/asr/transcription/Transcription.java b/src/main/java/com/alibaba/dashscope/audio/asr/transcription/Transcription.java index c970ae8..6362053 100644 --- a/src/main/java/com/alibaba/dashscope/audio/asr/transcription/Transcription.java +++ b/src/main/java/com/alibaba/dashscope/audio/asr/transcription/Transcription.java @@ -45,13 +45,18 @@ public TranscriptionResult asyncCall(TranscriptionParam param) { } public TranscriptionResult wait(TranscriptionQueryParam queryParam) { + return wait(queryParam, -1); + } + + public TranscriptionResult wait(TranscriptionQueryParam queryParam, long timeoutSeconds) { try { return TranscriptionResult.fromDashScopeResult( asyncApi.wait( queryParam.getTaskId(), queryParam.getApiKey(), baseUrl, - queryParam.getCustomHeaders())); + queryParam.getCustomHeaders(), + timeoutSeconds)); } catch (NoApiKeyException e) { throw new ApiException(e); } diff --git a/src/main/java/com/alibaba/dashscope/audio/qwen_asr/QwenTranscription.java b/src/main/java/com/alibaba/dashscope/audio/qwen_asr/QwenTranscription.java index 7f2983e..8d815d4 100644 --- a/src/main/java/com/alibaba/dashscope/audio/qwen_asr/QwenTranscription.java +++ b/src/main/java/com/alibaba/dashscope/audio/qwen_asr/QwenTranscription.java @@ -45,13 +45,18 @@ public QwenTranscriptionResult asyncCall(QwenTranscriptionParam param) { } public QwenTranscriptionResult wait(QwenTranscriptionQueryParam queryParam) { + return wait(queryParam, -1); + } + + public QwenTranscriptionResult wait(QwenTranscriptionQueryParam queryParam, long timeoutSeconds) { try { return QwenTranscriptionResult.fromDashScopeResult( asyncApi.wait( queryParam.getTaskId(), queryParam.getApiKey(), baseUrl, - queryParam.getCustomHeaders())); + queryParam.getCustomHeaders(), + timeoutSeconds)); } catch (NoApiKeyException e) { throw new ApiException(e); }