【代码新增】AI:开启 AI 租户的能力

This commit is contained in:
YunaiV 2024-07-05 09:42:36 +08:00
parent c98495dfcb
commit 2e73959a2c
9 changed files with 38 additions and 25 deletions

View File

@ -32,6 +32,11 @@
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.iocoder.boot</groupId>
<artifactId>yudao-spring-boot-starter-biz-tenant</artifactId>
</dependency>
<!-- Web 相关 -->
<dependency>
<groupId>cn.iocoder.boot</groupId>

View File

@ -2,6 +2,7 @@
POST {{baseUrl}}/ai/chat/message/send
Content-Type: application/json
Authorization: {{token}}
tenant-id: {{adminTenentId}}
{
"conversationId": "1781604279872581724",
@ -12,9 +13,10 @@ Authorization: {{token}}
POST {{baseUrl}}/ai/chat/message/send-stream
Content-Type: application/json
Authorization: {{token}}
tenant-id: {{adminTenentId}}
{
"conversationId": "1781604279872581690",
"conversationId": "1781604279872581724",
"content": "1+1=?"
}

View File

@ -57,6 +57,4 @@ public class AiImageRespVO {
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime createTime;
}

View File

@ -76,6 +76,11 @@ public class AiImageDO extends BaseDO {
*/
private Integer status;
/**
* 完成时间
*/
private LocalDateTime finishTime;
/**
* 绘画错误信息
*/
@ -112,11 +117,6 @@ public class AiImageDO extends BaseDO {
*/
private String taskId;
/**
* 完成时间
*/
private LocalDateTime finishTime;
public static class ButtonTypeHandler extends AbstractJsonTypeHandler<Object> {
@Override

View File

@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.ai.core.util.AiUtils;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
@ -125,11 +126,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
return success(new AiChatMessageSendRespVO().setSend(BeanUtils.toBean(userMessage, AiChatMessageSendRespVO.Message.class))
.setReceive(BeanUtils.toBean(assistantMessage, AiChatMessageSendRespVO.Message.class).setContent(newContent)));
}).doOnComplete(() -> {
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString()));
// 忽略租户因为 Flux 异步无法透传租户
TenantUtils.executeIgnore(() ->
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())));
}).doOnError(throwable -> {
// TODO @芋艿失败的情况下要不要删除消息
log.error("[sendChatMessageStream][userId({}) sendReqVO({}) 发生异常]", userId, sendReqVO, throwable);
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage()));
// 忽略租户因为 Flux 异步无法透传租户
TenantUtils.executeIgnore(() ->
chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(throwable.getMessage())));
}).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.CHAT_STREAM_ERROR)));
}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.ai.core.enums.AiPlatformEnum;
import cn.iocoder.yudao.framework.ai.core.util.AiUtils;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.ai.controller.admin.write.vo.AiWriteGenerateReqVO;
import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO;
import cn.iocoder.yudao.module.ai.dal.dataobject.write.AiWriteDO;
@ -75,10 +76,14 @@ public class AiWriteServiceImpl implements AiWriteService {
// 响应结果
return success(newContent);
}).doOnComplete(() -> {
writeMapper.updateById(new AiWriteDO().setId(writeDO.getId()).setGeneratedContent(contentBuffer.toString()));
// 忽略租户因为 Flux 异步无法透传租户
TenantUtils.executeIgnore(() ->
writeMapper.updateById(new AiWriteDO().setId(writeDO.getId()).setGeneratedContent(contentBuffer.toString())));
}).doOnError(throwable -> {
log.error("[AI Write][generateReqVO({}) 发生异常]", generateReqVO, throwable);
writeMapper.updateById(new AiWriteDO().setId(writeDO.getId()).setErrorMessage(throwable.getMessage()));
log.error("[generateWriteContent][generateReqVO({}) 发生异常]", generateReqVO, throwable);
// 忽略租户因为 Flux 异步无法透传租户
TenantUtils.executeIgnore(() ->
writeMapper.updateById(new AiWriteDO().setId(writeDO.getId()).setErrorMessage(throwable.getMessage())));
}).onErrorResume(error -> Flux.just(error(ErrorCodeConstants.WRITE_STREAM_ERROR)));
}

View File

@ -163,7 +163,7 @@ public class AiClientFactoryImpl implements AiClientFactory {
* 可参考 {@link QianFanAutoConfiguration#qianFanChatModel(QianFanConnectionProperties, QianFanChatProperties, RestClient.Builder, RetryTemplate, ResponseErrorHandler)}
*/
private static QianFanChatModel buildYiYanChatClient(String key) {
// TODO 芋艿貌似目前设置request 势必会报错
// TODO @xin貌似目前设置request 势必会报错看看能不能有办法参考 buildQianWenChatClient调用 QianFanAutoConfiguration#qianFanChatModel初始化当然 key 要用自己的哈
List<String> keys = StrUtil.split(key, '|');
Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式");
String appKey = keys.get(0);
@ -191,8 +191,8 @@ public class AiClientFactoryImpl implements AiClientFactory {
private static TongYiChatModel buildQianWenChatClient(String key) {
com.alibaba.dashscope.aigc.generation.Generation generation = SpringUtil.getBean(Generation.class);
TongYiChatProperties chatOptions = SpringUtil.getBean(TongYiChatProperties.class);
// TODO @芋艿貌似 apiKey 是全局唯一的得测试下
// TODO @芋艿貌似阿里云不是增量返回的
// TODO @xin貌似 apiKey 是全局唯一的得测试下
// TODO @xin貌似阿里云不是增量返回的
TongYiConnectionProperties connectionProperties = new TongYiConnectionProperties();
connectionProperties.setApiKey(key);
return new TongYiAutoConfiguration().tongYiChatClient(generation, chatOptions, connectionProperties);

View File

@ -70,12 +70,6 @@ spring:
port: 6379 # 端口
database: 0 # 数据库索引
# password: dev # 密码,建议生产环境开启
server:
servlet:
encoding:
enabled: true
charset: UTF-8
force: true
--- #################### 定时任务相关配置 ####################
@ -226,8 +220,6 @@ yudao:
enable: false
demo: false # 关闭演示模式
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
tenant:
enable: false
justauth:
enabled: true

View File

@ -34,6 +34,13 @@ spring:
redis:
time-to-live: 1h # 设置过期时间为 1 小时
server:
servlet:
encoding:
enabled: true
charset: UTF-8 # 必须设置 UTF-8避免 WebFlux 流式返回AI 场景)会乱码问题
force: true
--- #################### 接口文档配置 ####################
springdoc: