All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.dashscope.conversation.Conversation Maven / Gradle / Ivy

// Copyright (c) Alibaba, Inc. and its affiliates.
package com.alibaba.dashscope.conversation;

import com.alibaba.dashscope.BaseConversation;
import com.alibaba.dashscope.common.Protocol;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.common.Status;
import com.alibaba.dashscope.conversation.rpc.ConversationHttpRpc;
import com.alibaba.dashscope.conversation.rpc.ConversationRpc;
import com.alibaba.dashscope.conversation.rpc.ConversationWebsocketRpc;
import com.google.common.collect.Lists;
import io.reactivex.BackpressureStrategy;
import io.reactivex.Flowable;
import io.reactivex.FlowableEmitter;
import java.util.List;
import java.util.concurrent.TimeUnit;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public final class Conversation implements BaseConversation {

  private final ConversationRpc conversationRpc;

  @Setter private long observerTimeout = 30;

  @Getter private final List history = Lists.newCopyOnWriteArrayList();

  public Conversation() {
    conversationRpc = new ConversationHttpRpc();
  }

  public Conversation(String protocol) {
    if (Protocol.WEBSOCKET.getValue().equals(protocol)) {
      conversationRpc = new ConversationWebsocketRpc();
    } else {
      conversationRpc = new ConversationHttpRpc();
    }
  }

  /**
   * Call the server to get the result in the callback function.
   *
   * @param param The input param of class `ConversationParam`.
   * @param callback The callback to receive response, the template class is `ConversationResult`.
   */
  @Override
  public void call(ConversationParam param, ResultCallback callback) {
    class ReactCallback extends ResultCallback {

      public void onOpen(Status status) {
        callback.onOpen(status);
      }

      @Override
      public void onEvent(String type, ConversationResult message) {
        if (EventType.TASK_FINISHED.getValue().equals(type) && (message != null)) {
          history.add(
              ChatMessage.builder().role(Role.USER.getValue()).payload(param.getPrompt()).build());
          history.add(
              ChatMessage.builder()
                  .role(Role.BOT.getValue())
                  .payload(message.getMessage().getPayload())
                  .build());
        }
        callback.onEvent(type, message);
      }

      public void onClose(Status status) {
        callback.onClose(status);
      }

      @Override
      public void onError(Exception e) {
        callback.onError(e);
      }

      public void doClose(Status status) {
        callback.doClose(status);
      }
    }
    if (param.getHistory() == null) {
      param.setHistory(history);
    }
    conversationRpc.call(param, new ReactCallback());
  }

  /**
   * Call the server to get the result by stream.
   *
   * @param param The input param of class `ConversationParam`.
   * @return A `Flowable` of the output structure.
   */
  @Override
  public Flowable streamCall(ConversationParam param) {
    class ReactCallback extends ResultCallback {

      private final FlowableEmitter emitter;

      public ReactCallback(FlowableEmitter emitter) {
        this.emitter = emitter;
      }

      @Override
      public void onEvent(String type, ConversationResult message) {
        if (EventType.RESULT_GENERATED.getValue().equals(type) && param.isStream()) {
          this.emitter.onNext(message);
        } else if (EventType.TASK_FINISHED.getValue().equals(type) && (message != null)) {
          history.add(
              ChatMessage.builder().role(Role.USER.getValue()).payload(param.getPrompt()).build());
          history.add(
              ChatMessage.builder()
                  .role(Role.BOT.getValue())
                  .payload(message.getMessage() == null ? null : message.getMessage().getPayload())
                  .build());
          this.emitter.onNext(message);
          this.emitter.onComplete();
        }
      }

      @Override
      public void onError(Exception e) {
        this.emitter.onError(e);
      }
    }

    if (param.getHistory() == null) {
      param.setHistory(history);
    }
    param.setStream(true);
    return Flowable.create(
            emitter -> conversationRpc.call(param, new ReactCallback(emitter)),
            BackpressureStrategy.BUFFER)
        .timeout(observerTimeout, TimeUnit.SECONDS);
  }

  /**
   * Call the server to get the whole result.
   *
   * @param param The input param of class `ConversationParam`.
   * @return The output structure of `QWenConversationResult`.
   */
  @Override
  public ConversationResult call(ConversationParam param) {

    class ReactCallback extends ResultCallback {

      private final FlowableEmitter emitter;

      public ReactCallback(FlowableEmitter emitter) {
        this.emitter = emitter;
      }

      @Override
      public void onEvent(String type, ConversationResult message) {
        if (EventType.TASK_FINISHED.getValue().equals(type)) {
          this.emitter.onNext(message);
          this.emitter.onComplete();
        }
      }

      @Override
      public void onError(Exception e) {
        this.emitter.onError(e);
      }
    }

    if (param.getHistory() == null && !history.isEmpty()) {
      param.setHistory(history);
    }
    param.setStream(false);
    Flowable flowable =
        Flowable.create(
                emitter -> conversationRpc.call(param, new ReactCallback(emitter)),
                BackpressureStrategy.BUFFER)
            .timeout(observerTimeout, TimeUnit.SECONDS);
    ConversationResult result = flowable.blockingFirst();
    if (result != null) {
      history.add(
          ChatMessage.builder().role(Role.USER.getValue()).payload(param.getPrompt()).build());
      history.add(
          ChatMessage.builder()
              .role(Role.BOT.getValue())
              .payload(result.getMessage().getPayload())
              .build());
    }
    return result;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy