mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2025-01-31 17:40:05 +08:00
增加阿里 通义千问
This commit is contained in:
parent
de32611794
commit
0f73b61db2
@ -108,6 +108,12 @@
|
|||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<!-- 阿里云 通义千问 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun</groupId>
|
||||||
|
<artifactId>broadscope-bailian-sdk-java</artifactId>
|
||||||
|
<version>1.3.0</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</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) {
|
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
System.err.println(authUrl);
|
|
||||||
System.err.println(JSONUtil.toJsonPrettyStr(request));
|
|
||||||
// wss 请求的 URI
|
// wss 请求的 URI
|
||||||
URI uri = URI.create(authUrl);
|
URI uri = URI.create(authUrl);
|
||||||
// 发起 wss 请求并处理响应
|
// 发起 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