mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-19 03:30:06 +08:00
增加阿里 通义千问
This commit is contained in:
parent
de32611794
commit
0f73b61db2
@ -108,6 +108,12 @@
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
</dependency>
|
||||
<!-- 阿里云 通义千问 -->
|
||||
<dependency>
|
||||
<groupId>com.aliyun</groupId>
|
||||
<artifactId>broadscope-bailian-sdk-java</artifactId>
|
||||
<version>1.3.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,82 @@
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen;
|
||||
|
||||
import com.aliyun.broadscope.bailian.sdk.AccessTokenClient;
|
||||
import com.aliyun.broadscope.bailian.sdk.ApplicationClient;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.CompletionsRequest;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse;
|
||||
import lombok.Getter;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 阿里 通义千问
|
||||
*
|
||||
* https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all
|
||||
*
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:09
|
||||
*/
|
||||
@Getter
|
||||
public class QianWenApi {
|
||||
|
||||
/**
|
||||
* accessKeyId、accessKeySecret、agentKey、appId 获取方式如下链接
|
||||
* https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp
|
||||
*/
|
||||
private String accessKeyId;
|
||||
private String accessKeySecret;
|
||||
private String agentKey;
|
||||
private String appId;
|
||||
private String endpoint = "bailian.cn-beijing.aliyuncs.com";
|
||||
private String token;
|
||||
private ApplicationClient client;
|
||||
|
||||
public QianWenApi(String accessKeyId, String accessKeySecret, String agentKey, String appId, String endpoint) {
|
||||
this.accessKeyId = accessKeyId;
|
||||
this.accessKeySecret = accessKeySecret;
|
||||
this.agentKey = agentKey;
|
||||
this.appId = appId;
|
||||
|
||||
if (endpoint != null) {
|
||||
this.endpoint = endpoint;
|
||||
}
|
||||
|
||||
// 获取token
|
||||
AccessTokenClient accessTokenClient = new AccessTokenClient(accessKeyId, accessKeySecret, agentKey);
|
||||
token = accessTokenClient.getToken();
|
||||
// 构建client
|
||||
client = ApplicationClient.builder()
|
||||
.token(token)
|
||||
.build();
|
||||
}
|
||||
|
||||
public ResponseEntity<CompletionsResponse> chatCompletionEntity(ChatRequestMessage message) {
|
||||
// 创建request
|
||||
CompletionsRequest request = new CompletionsRequest()
|
||||
.setAppId(appId)
|
||||
.setMessages(List.of(message))
|
||||
.setParameters(new CompletionsRequest.Parameter().setResultFormat("message"));
|
||||
//
|
||||
CompletionsResponse response = client.completions(request);
|
||||
int httpCode = 200;
|
||||
if (!response.isSuccess()) {
|
||||
System.out.printf("failed to create completion, requestId: %s, code: %s, message: %s\n",
|
||||
response.getRequestId(), response.getCode(), response.getMessage());
|
||||
httpCode = 500;
|
||||
}
|
||||
return new ResponseEntity<>(response, HttpStatusCode.valueOf(httpCode));
|
||||
}
|
||||
|
||||
public Flux<CompletionsResponse> chatCompletionStream(ChatRequestMessage message) {
|
||||
return client.streamCompletions(
|
||||
new CompletionsRequest()
|
||||
.setAppId(appId)
|
||||
.setMessages(List.of(message))
|
||||
.setParameters(new CompletionsRequest.Parameter().setIncrementalOutput(true))
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen;
|
||||
|
||||
import cn.iocoder.yudao.framework.ai.chat.ChatClient;
|
||||
import cn.iocoder.yudao.framework.ai.chat.ChatResponse;
|
||||
import cn.iocoder.yudao.framework.ai.chat.Generation;
|
||||
import cn.iocoder.yudao.framework.ai.chat.StreamingChatClient;
|
||||
import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
|
||||
import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionMessage;
|
||||
import cn.iocoder.yudao.framework.ai.chatqianwen.api.QianWenChatCompletionRequest;
|
||||
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletion;
|
||||
import cn.iocoder.yudao.framework.ai.chatyiyan.api.YiYanChatCompletionRequest;
|
||||
import cn.iocoder.yudao.framework.ai.chatyiyan.exception.YiYanApiException;
|
||||
import cn.iocoder.yudao.framework.ai.model.function.AbstractFunctionCallSupport;
|
||||
import cn.iocoder.yudao.framework.ai.model.function.FunctionCallbackContext;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.retry.RetryCallback;
|
||||
import org.springframework.retry.RetryContext;
|
||||
import org.springframework.retry.RetryListener;
|
||||
import org.springframework.retry.support.RetryTemplate;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 阿里 通义千问 client
|
||||
*
|
||||
* 文档地址:https://help.aliyun.com/document_detail/2587494.html?spm=a2c4g.2587492.0.0.53f33c566sXskp
|
||||
*
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:06
|
||||
*/
|
||||
@Slf4j
|
||||
public class QianWenChatClient extends AbstractFunctionCallSupport<QianWenChatCompletionMessage, ChatRequestMessage, ResponseEntity<CompletionsResponse>>
|
||||
implements ChatClient, StreamingChatClient {
|
||||
|
||||
private QianWenApi qianWenApi;
|
||||
|
||||
public QianWenChatClient(QianWenApi qianWenApi) {
|
||||
super(null);
|
||||
this.qianWenApi = qianWenApi;
|
||||
}
|
||||
|
||||
public final RetryTemplate retryTemplate = RetryTemplate.builder()
|
||||
// 最大重试次数 10
|
||||
.maxAttempts(10)
|
||||
.retryOn(YiYanApiException.class)
|
||||
// 最大重试5次,第一次间隔3000ms,第二次3000ms * 2,第三次3000ms * 3,以此类推,最大间隔3 * 60000ms
|
||||
.exponentialBackoff(Duration.ofMillis(3000), 2, Duration.ofMillis(3 * 60000))
|
||||
.withListener(new RetryListener() {
|
||||
@Override
|
||||
public <T extends Object, E extends Throwable> void onError(RetryContext context,
|
||||
RetryCallback<T, E> callback, Throwable throwable) {
|
||||
log.warn("重试异常:" + context.getRetryCount(), throwable);
|
||||
};
|
||||
})
|
||||
.build();
|
||||
|
||||
public QianWenChatClient(FunctionCallbackContext functionCallbackContext) {
|
||||
super(functionCallbackContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatResponse call(Prompt prompt) {
|
||||
return this.retryTemplate.execute(ctx -> {
|
||||
// ctx 会有重试的信息
|
||||
// 创建 request 请求,stream模式需要供应商支持
|
||||
ChatRequestMessage request = this.createRequest(prompt, false);
|
||||
// 调用 callWithFunctionSupport 发送请求
|
||||
ResponseEntity<CompletionsResponse> responseEntity = this.callWithFunctionSupport(request);
|
||||
// 获取结果封装 chatCompletion
|
||||
CompletionsResponse response = responseEntity.getBody();
|
||||
if (!response.isSuccess()) {
|
||||
return new ChatResponse(List.of(new Generation(String.format("failed to create completion, requestId: %s, code: %s, message: %s\n",
|
||||
response.getRequestId(), response.getCode(), response.getMessage()))));
|
||||
}
|
||||
List<Generation> generations = response.getData().getChoices().stream()
|
||||
.map(item -> new Generation(item.getMessage().getContent())).collect(Collectors.toList());
|
||||
return new ChatResponse(generations);
|
||||
});
|
||||
}
|
||||
|
||||
private ChatRequestMessage createRequest(Prompt prompt, boolean b) {
|
||||
return new ChatUserMessage(prompt.getContents());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<ChatResponse> stream(Prompt prompt) {
|
||||
// ctx 会有重试的信息
|
||||
// 创建 request 请求,stream模式需要供应商支持
|
||||
ChatRequestMessage request = this.createRequest(prompt, true);
|
||||
// 调用 callWithFunctionSupport 发送请求
|
||||
Flux<CompletionsResponse> response = this.qianWenApi.chatCompletionStream(request);
|
||||
return response.map(res -> {
|
||||
return new ChatResponse(List.of(new Generation(res.getData().getText())));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QianWenChatCompletionRequest doCreateToolResponseRequest(ChatRequestMessage previousRequest, QianWenChatCompletionMessage responseMessage, List<QianWenChatCompletionMessage> conversationHistory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<QianWenChatCompletionMessage> doGetUserMessages(ChatRequestMessage request) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QianWenChatCompletionMessage doGetToolResponseMessage(ResponseEntity<CompletionsResponse> response) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseEntity<CompletionsResponse> doChatCompletion(ChatRequestMessage request) {
|
||||
return qianWenApi.chatCompletionEntity(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isToolFunctionCall(ResponseEntity<CompletionsResponse> response) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen.api;
|
||||
|
||||
import com.aliyun.broadscope.bailian.sdk.models.CompletionsResponse;
|
||||
|
||||
/**
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:07
|
||||
*/
|
||||
public class QianWenChatCompletion extends CompletionsResponse {
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen.api;
|
||||
|
||||
/**
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:07
|
||||
*/
|
||||
public class QianWenChatCompletionMessage {
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen.api;
|
||||
|
||||
import com.aliyun.broadscope.bailian.sdk.models.ChatRequestMessage;
|
||||
import com.aliyun.broadscope.bailian.sdk.models.ChatUserMessage;
|
||||
|
||||
/**
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:07
|
||||
*/
|
||||
public class QianWenChatCompletionRequest extends ChatRequestMessage {
|
||||
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* 阿里的 通义千问
|
||||
*
|
||||
* 链接:https://www.aliyun.com/search?k=%E9%80%9A%E4%B9%89%E5%A4%A7%E6%A8%A1%E5%9E%8B&scene=all
|
||||
*
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:05
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.ai.chatqianwen;
|
@ -132,8 +132,6 @@ public class XingHuoApi {
|
||||
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
System.err.println(authUrl);
|
||||
System.err.println(JSONUtil.toJsonPrettyStr(request));
|
||||
// wss 请求的 URI
|
||||
URI uri = URI.create(authUrl);
|
||||
// 发起 wss 请求并处理响应
|
||||
|
@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.framework.ai.chat;
|
||||
|
||||
import cn.iocoder.yudao.framework.ai.chat.prompt.Prompt;
|
||||
import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenApi;
|
||||
import cn.iocoder.yudao.framework.ai.chatqianwen.QianWenChatClient;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* author: fansili
|
||||
* time: 2024/3/13 21:37
|
||||
*/
|
||||
public class QianWenChatClientTests {
|
||||
|
||||
private QianWenChatClient qianWenChatClient;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
QianWenApi qianWenApi = new QianWenApi(
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
null
|
||||
);
|
||||
qianWenChatClient = new QianWenChatClient(qianWenApi);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callTest() {
|
||||
ChatResponse call = qianWenChatClient.call(new Prompt("Java语言怎么样?"));
|
||||
System.err.println(call.getResult());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void streamTest() {
|
||||
Flux<ChatResponse> flux = qianWenChatClient.stream(new Prompt("Java语言怎么样?"));
|
||||
flux.subscribe(new Consumer<ChatResponse>() {
|
||||
@Override
|
||||
public void accept(ChatResponse chatResponse) {
|
||||
System.err.print(chatResponse.getResult().getOutput().getContent());
|
||||
}
|
||||
});
|
||||
|
||||
// 阻止退出
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
scanner.nextLine();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user