Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
shun peng
/
lufa-ai
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
82c57840
authored
Apr 14, 2025
by
彭顺
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 4月11日需求修改
parent
68f10d90
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
497 additions
and
90 deletions
+497
-90
.DS_Store
+0
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/AgentChatController.java
+195
-31
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentCreateReqVO.java
+3
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentFeedBackReqVO.java
+24
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentMsgReqVO.java
+6
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentUsedRespVO.java
+4
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java
+52
-10
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageFeedBackReqVO.java
+25
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java
+10
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java
+8
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java
+3
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java
+21
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java
+28
-10
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java
+5
-5
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java
+5
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
+52
-15
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
+1
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
+1
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTApi.java
+14
-8
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTChatModel.java
+1
-1
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTOptions.java
+24
-0
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
+2
-2
ruoyi-vue-pro-master-jdk17/yudao-server/.DS_Store
+0
-0
ruoyi-vue-pro-master-jdk17/yudao-server/src/main/resources/application.yaml
+1
-0
yudao-ui-admin-vue3/.DS_Store
+0
-0
yudao-ui-admin-vue3/src/api/ai/chat/message/index.ts
+2
-0
yudao-ui-admin-vue3/src/types/auto-components.d.ts
+2
-0
yudao-ui-admin-vue3/src/views/ai/chat/manager/ChatMessageList.vue
+6
-0
yudao-ui-admin-vue3/src/views/infra/file/FileForm.vue
+2
-2
No files found.
.DS_Store
0 → 100644
View file @
82c57840
File added
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/AgentChatController.java
View file @
82c57840
package
cn
.
iocoder
.
yudao
.
module
.
ai
.
controller
.
admin
.
agent
;
import
cn.iocoder.yudao.framework.common.pojo.CommonResult
;
import
cn.iocoder.yudao.framework.common.util.object.BeanUtils
;
import
cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentCreateReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentMsgReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.agent.vo.AgentUsedRespVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.agent.vo.OrderInfoVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.agent.vo.*
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.model.AiApiKeyDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO
;
...
...
@@ -17,12 +12,16 @@ import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService;
import
cn.iocoder.yudao.module.ai.service.model.AiApiKeyService
;
import
cn.iocoder.yudao.module.ai.service.model.AiChatModelService
;
import
cn.iocoder.yudao.module.ai.service.model.AiChatRoleService
;
import
com.fasterxml.jackson.core.JsonProcessingException
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
io.swagger.v3.oas.annotations.Operation
;
import
io.swagger.v3.oas.annotations.Parameter
;
import
io.swagger.v3.oas.annotations.tags.Tag
;
import
jakarta.annotation.Resource
;
import
jakarta.annotation.security.PermitAll
;
import
jakarta.validation.Valid
;
import
org.json.JSONArray
;
import
org.json.JSONObject
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.*
;
import
org.springframework.validation.annotation.Validated
;
...
...
@@ -89,7 +88,7 @@ public class AgentChatController {
AgentUsedRespVO
agentUsedRespVO
=
new
AgentUsedRespVO
();
agentUsedRespVO
.
setId
(
aiChatConversationDO
.
getId
());
agentUsedRespVO
.
setRoleId
(
aiChatConversationDO
.
getRoleId
());
agentUsedRespVO
.
setTitle
(
aiChatConversationDO
.
getTitle
());
agentUsedRespVO
.
setCreateTime
(
aiChatConversationDO
.
getCreateTime
());
AiChatRoleDO
aiChatRoleDO
=
chatRoleService
.
getChatRole
(
aiChatConversationDO
.
getRoleId
());
...
...
@@ -106,13 +105,13 @@ public class AgentChatController {
return
success
(
result
);
}
@PostMapping
(
"/get-messages"
)
@Operation
(
summary
=
"获得智能体对话消息"
)
public
ResponseEntity
<?>
getAgentMessages
(
@RequestBody
@Valid
AgentMsgReqVO
reqVO
)
{
@GetMapping
(
"/get-extra-variables"
)
@Operation
(
summary
=
"获得智能体额外选项"
)
@Parameter
(
name
=
"roleId"
,
required
=
true
,
description
=
"智能体ID"
,
example
=
"1024"
)
public
ResponseEntity
<?>
getAgentExtraVariables
(
@RequestParam
(
"roleId"
)
Long
roleId
)
{
AiChatRoleDO
aiRole
=
chatRoleService
.
getChatRole
(
reqVO
.
getRoleId
());
AiChatConversationDO
conversation
=
chatConversationService
.
getChatConversation
(
reqVO
.
getConversationId
());
AiChatModelDO
model
=
chatModelService
.
getChatModel
(
conversation
.
getModelId
());
AiChatRoleDO
aiRole
=
chatRoleService
.
getChatRole
(
roleId
);
AiChatModelDO
model
=
chatModelService
.
getChatModel
(
aiRole
.
getModelId
());
AiApiKeyDO
apiKeyDO
=
apiKeyService
.
getApiKey
(
model
.
getKeyId
());
// 目标服务的URL
...
...
@@ -120,9 +119,7 @@ public class AgentChatController {
// 构建请求参数
String
appId
=
aiRole
.
getAppId
();
String
chatId
=
String
.
valueOf
(
reqVO
.
getConversationId
());
// String appId = "66f225d52b2887652b418f82";
// String chatId = "1781604279872581766";
String
chatId
=
"any_id_can_works"
;
boolean
loadCustomFeedbacks
=
true
;
// 构建URL与请求参数
...
...
@@ -139,20 +136,36 @@ public class AgentChatController {
// 发送请求并接收响应
ResponseEntity
<
String
>
response
=
restTemplate
.
exchange
(
requestUrl
,
HttpMethod
.
GET
,
entity
,
String
.
class
);
// 返回响应
return
response
;
JSONObject
initJson
=
new
JSONObject
(
response
.
getBody
());
JSONObject
initData
=
initJson
.
getJSONObject
(
"data"
);
JSONArray
variablesConfig
=
initData
.
getJSONObject
(
"app"
)
.
getJSONObject
(
"chatConfig"
)
.
optJSONArray
(
"variables"
);
JSONObject
data
=
new
JSONObject
();
data
.
put
(
"status"
,
200
);
data
.
put
(
"data"
,
variablesConfig
);
data
.
put
(
"msg"
,
""
);
// 4. 返回合并后的响应
return
ResponseEntity
.
ok
(
data
.
toString
());
}
@Operation
(
summary
=
"删除指定对话的上下文"
)
@DeleteMapping
(
"/delete-context"
)
@Parameter
(
name
=
"conversationId"
,
required
=
true
,
description
=
"对话编号"
,
example
=
"1024"
)
public
ResponseEntity
<?>
deleteChatMessageByConversationId
(
@RequestParam
(
"conversationId"
)
Long
conversationId
)
{
@PostMapping
(
"/get-messages"
)
@Operation
(
summary
=
"获得智能体对话消息"
)
public
ResponseEntity
<?>
getAgentMessagesv2
(
@RequestBody
@Valid
AgentMsgReqVO
reqVO
)
{
if
(
chatMessageService
.
checkMsgExist
(
reqVO
.
getConversationId
())){
// 直接构建 JSON 字符串
String
jsonResponse
=
"{ \"code\": 200, \"data\": {}, \"msg\": \"\" }"
;
AiChatConversationDO
conversation
=
chatConversationService
.
getChatConversation
(
conversationId
);
if
(
conversation
.
getRoleId
()
==
null
){
throw
exception
(
CHAT_AGENT_NOT_EXISTS
)
;
// 创建 ResponseEntity
ResponseEntity
<
String
>
response
=
ResponseEntity
.
ok
(
jsonResponse
);
return
response
;
}
AiChatRoleDO
aiRole
=
chatRoleService
.
getChatRole
(
conversation
.
getRoleId
());
AiChatRoleDO
aiRole
=
chatRoleService
.
getChatRole
(
reqVO
.
getRoleId
());
AiChatConversationDO
conversation
=
chatConversationService
.
getChatConversation
(
reqVO
.
getConversationId
());
AiChatModelDO
model
=
chatModelService
.
getChatModel
(
conversation
.
getModelId
());
AiApiKeyDO
apiKeyDO
=
apiKeyService
.
getApiKey
(
model
.
getKeyId
());
...
...
@@ -161,10 +174,20 @@ public class AgentChatController {
// 构建请求参数
String
appId
=
aiRole
.
getAppId
();
String
chatId
=
String
.
valueOf
(
conversationId
);
String
chatId
=
String
.
valueOf
(
reqVO
.
getConversationId
());
boolean
loadCustomFeedbacks
=
true
;
// 构建请求体
Map
<
String
,
Object
>
requestBody
=
new
HashMap
<>();
requestBody
.
put
(
"offset"
,
reqVO
.
getOffset
());
requestBody
.
put
(
"pageSize"
,
reqVO
.
getPageSize
());
requestBody
.
put
(
"chatId"
,
chatId
);
requestBody
.
put
(
"appId"
,
appId
);
requestBody
.
put
(
"loadCustomFeedbacks"
,
loadCustomFeedbacks
);
requestBody
.
put
(
"type"
,
"normal"
);
// 构建URL与请求参数
String
requestUrl
=
baseUrl
+
"/core/chat/
delHistory?appId="
+
appId
+
"&chatId="
+
chatId
;
String
requestUrl
=
baseUrl
+
"/core/chat/
getPaginationRecords"
;
// 设置请求头
HttpHeaders
headers
=
new
HttpHeaders
();
...
...
@@ -172,15 +195,97 @@ public class AgentChatController {
headers
.
set
(
"Authorization"
,
"Bearer "
+
apiKeyDO
.
getApiKey
());
// 构建请求实体
HttpEntity
<
String
>
entity
=
new
HttpEntity
<>(
headers
);
HttpEntity
<
Map
<
String
,
Object
>>
entity
=
new
HttpEntity
<>(
requestBody
,
headers
);
// 发送请求并接收响应
ResponseEntity
<
String
>
response
=
restTemplate
.
exchange
(
requestUrl
,
HttpMethod
.
DELETE
,
entity
,
String
.
class
);
ResponseEntity
<
String
>
response
=
restTemplate
.
exchange
(
requestUrl
,
HttpMethod
.
POST
,
entity
,
String
.
class
);
chatMessageService
.
deleteChatMessageByConversationId
(
conversationId
,
getLoginUserId
());
// 返回响应
return
response
;
}
// @PostMapping("/get-messages")
// @Operation(summary = "获得智能体对话消息")
// public ResponseEntity<?> getAgentMessagesv2(@RequestBody @Valid AgentMsgReqVO reqVO) {
// if(chatMessageService.checkMsgExist(reqVO.getConversationId())) {
// // 直接构建 JSON 字符串
// String jsonResponse = "{ \"code\": 200, \"data\": {}, \"msg\": \"\" }";
// // 创建 ResponseEntity
// return ResponseEntity.ok(jsonResponse);
// }
//
// AiChatRoleDO aiRole = chatRoleService.getChatRole(reqVO.getRoleId());
// AiChatConversationDO conversation = chatConversationService.getChatConversation(reqVO.getConversationId());
// AiChatModelDO model = chatModelService.getChatModel(conversation.getModelId());
// AiApiKeyDO apiKeyDO = apiKeyService.getApiKey(model.getKeyId());
//
// // 目标服务的URL
// String baseUrl = apiKeyDO.getUrl();
//
// // 构建请求参数
// String appId = aiRole.getAppId();
// String chatId = String.valueOf(reqVO.getConversationId());
// boolean loadCustomFeedbacks = true;
//
// // 1. 首先获取init数据
// String initUrl = baseUrl + "/core/chat/init?appId=" + appId + "&chatId=" + chatId + "&loadCustomFeedbacks=" + loadCustomFeedbacks;
// HttpHeaders headers = new HttpHeaders();
// headers.setContentType(MediaType.APPLICATION_JSON);
// headers.set("Authorization", "Bearer " + apiKeyDO.getApiKey());
// HttpEntity<String> initEntity = new HttpEntity<>(headers);
// ResponseEntity<String> initResponse = restTemplate.exchange(initUrl, HttpMethod.GET, initEntity, String.class);
//
// // 解析init响应获取variables和app.chatConfig.variables
// JSONObject initJson = new JSONObject(initResponse.getBody());
// JSONObject initData = initJson.getJSONObject("data");
//// JSONObject variables = initData.optJSONObject("variables");
// JSONArray variablesConfig = initData.getJSONObject("app")
// .getJSONObject("chatConfig")
// .optJSONArray("variables");
//
// // 2. 获取分页记录
// Map<String, Object> requestBody = new HashMap<>();
// requestBody.put("offset", reqVO.getOffset());
// requestBody.put("pageSize", reqVO.getPageSize());
// requestBody.put("chatId", chatId);
// requestBody.put("appId", appId);
// requestBody.put("loadCustomFeedbacks", loadCustomFeedbacks);
// requestBody.put("type", "normal");
//
// String recordsUrl = baseUrl + "/core/chat/getPaginationRecords";
// HttpEntity<Map<String, Object>> recordsEntity = new HttpEntity<>(requestBody, headers);
// ResponseEntity<String> recordsResponse = restTemplate.exchange(recordsUrl, HttpMethod.POST, recordsEntity, String.class);
//
// // 3. 合并数据到分页记录响应中
// JSONObject recordsJson = new JSONObject(recordsResponse.getBody());
// JSONObject data = recordsJson.optJSONObject("data");
// if (data == null) {
// data = new JSONObject();
// recordsJson.put("data", data);
// }
//
// // 合并variables和variablesConfig
//// if (variables != null) {
//// data.put("variables", variables);
//// }
// if (variablesConfig != null) {
// data.put("variables", variablesConfig);
// }
//
// // 4. 返回合并后的响应
// return ResponseEntity.ok(recordsJson.toString());
// }
@Operation
(
summary
=
"删除指定对话的上下文"
)
@DeleteMapping
(
"/delete-context"
)
@Parameter
(
name
=
"conversationId"
,
required
=
true
,
description
=
"对话编号"
,
example
=
"1024"
)
public
CommonResult
<
Boolean
>
deleteChatMessageByConversationId
(
@RequestParam
(
"conversationId"
)
Long
conversationId
)
{
chatMessageService
.
deleteChatMessageByConversationId
(
conversationId
,
getLoginUserId
());
return
success
(
true
);
}
@PostMapping
(
"/get-order-info"
)
@Operation
(
summary
=
"获取jp通知单所需信息"
)
@Parameter
(
name
=
"vbeln"
,
required
=
true
,
description
=
"SAP销售订单编号"
,
example
=
"2024102922"
)
...
...
@@ -204,4 +309,63 @@ public class AgentChatController {
return
success
(
orderInfoService
.
getOrderInfoRequest
(
url
,
payload
));
}
@PostMapping
(
"/feedback"
)
@Operation
(
summary
=
"更新反馈信息"
)
public
ResponseEntity
<?>
updateUserFeedback
(
@RequestBody
@Valid
AgentFeedBackReqVO
reqVO
)
{
AiChatRoleDO
aiRole
=
chatRoleService
.
getChatRole
(
reqVO
.
getRoleId
());
AiChatConversationDO
conversation
=
chatConversationService
.
getChatConversation
(
reqVO
.
getConversationId
());
AiChatModelDO
model
=
chatModelService
.
getChatModel
(
conversation
.
getModelId
());
AiApiKeyDO
apiKeyDO
=
apiKeyService
.
getApiKey
(
model
.
getKeyId
());
// 目标服务的URL
String
baseUrl
=
apiKeyDO
.
getUrl
();
// 构建请求参数
String
appId
=
aiRole
.
getAppId
();
String
chatId
=
String
.
valueOf
(
reqVO
.
getConversationId
());
String
chatItemId
=
reqVO
.
getMessageId
();
String
userBadFeedback
=
reqVO
.
getUserBadFeedback
();
String
userGoodFeedback
=
reqVO
.
getUserGoodFeedback
();
// 构建请求体
Map
<
String
,
Object
>
requestBody
=
new
HashMap
<>();
requestBody
.
put
(
"appId"
,
appId
);
requestBody
.
put
(
"chatId"
,
chatId
);
requestBody
.
put
(
"chatItemId"
,
chatItemId
);
// 判断 userBadFeedback 和 userGoodFeedback 哪个不为 null
if
(
userBadFeedback
!=
null
)
{
requestBody
.
put
(
"userBadFeedback"
,
userBadFeedback
);
}
else
if
(
userGoodFeedback
!=
null
)
{
requestBody
.
put
(
"userGoodFeedback"
,
userGoodFeedback
);
}
// 将请求体转换为JSON字符串
ObjectMapper
objectMapper
=
new
ObjectMapper
();
String
requestBodyJson
;
try
{
requestBodyJson
=
objectMapper
.
writeValueAsString
(
requestBody
);
}
catch
(
JsonProcessingException
e
)
{
throw
new
RuntimeException
(
"Failed to convert request body to JSON"
,
e
);
}
// 构建URL与请求参数
String
requestUrl
=
baseUrl
+
"/core/chat/feedback/updateUserFeedback"
;
// 设置请求头
HttpHeaders
headers
=
new
HttpHeaders
();
headers
.
setContentType
(
MediaType
.
APPLICATION_JSON
);
headers
.
set
(
"Authorization"
,
"Bearer "
+
apiKeyDO
.
getApiKey
());
// 构建请求实体
HttpEntity
<
String
>
entity
=
new
HttpEntity
<>(
requestBodyJson
,
headers
);
// 发送请求并接收响应
ResponseEntity
<
String
>
response
=
restTemplate
.
exchange
(
requestUrl
,
HttpMethod
.
POST
,
entity
,
String
.
class
);
// 返回响应
return
response
;
}
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentCreateReqVO.java
View file @
82c57840
...
...
@@ -10,4 +10,7 @@ public class AgentCreateReqVO {
@Schema
(
description
=
"智能体编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"10"
)
private
Long
roleId
;
@Schema
(
description
=
"第一条消息作为标题"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"你好"
)
private
String
firstMsg
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentFeedBackReqVO.java
0 → 100644
View file @
82c57840
package
cn
.
iocoder
.
yudao
.
module
.
ai
.
controller
.
admin
.
agent
.
vo
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
lombok.Data
;
@Schema
(
description
=
"管理后台 - Agent FeedBack Request VO"
)
@Data
public
class
AgentFeedBackReqVO
{
@Schema
(
description
=
"智能体编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"32"
)
private
Long
roleId
;
@Schema
(
description
=
"对话编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"1024"
)
private
Long
conversationId
;
@Schema
(
description
=
"消息编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"1024"
)
private
String
messageId
;
@Schema
(
description
=
"好反馈"
,
example
=
"yes"
)
private
String
userGoodFeedback
;
@Schema
(
description
=
"坏反馈"
,
example
=
"回复效果差"
)
private
String
userBadFeedback
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentMsgReqVO.java
View file @
82c57840
...
...
@@ -11,4 +11,10 @@ public class AgentMsgReqVO {
@Schema
(
description
=
"对话编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"1024"
)
private
Long
conversationId
;
@Schema
(
description
=
"分页偏移"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"0"
)
private
Long
offset
;
@Schema
(
description
=
"分页大小"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"10"
)
private
Long
pageSize
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/agent/vo/AgentUsedRespVO.java
View file @
82c57840
...
...
@@ -20,6 +20,9 @@ public class AgentUsedRespVO {
@Trans
(
type
=
TransType
.
SIMPLE
,
target
=
AiChatRoleDO
.
class
,
fields
=
{
"name"
,
"avatar"
},
refs
=
{
"roleName"
,
"roleAvatar"
})
private
Long
roleId
;
@Schema
(
description
=
"对话标题"
,
example
=
"你好"
)
private
String
title
;
@Schema
(
description
=
"创建时间"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
LocalDateTime
createTime
;
...
...
@@ -28,7 +31,7 @@ public class AgentUsedRespVO {
@Schema
(
description
=
"智能体头像"
,
example
=
"https://www.iocoder.cn/1.png"
)
private
String
roleAvatar
;
@Schema
(
description
=
"智能体名字"
,
example
=
"
小黄
"
)
@Schema
(
description
=
"智能体名字"
,
example
=
"
政府PPT编制
"
)
private
String
roleName
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatMessageController.java
View file @
82c57840
...
...
@@ -8,10 +8,7 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import
cn.iocoder.yudao.framework.common.pojo.PageResult
;
import
cn.iocoder.yudao.framework.common.util.collection.MapUtils
;
import
cn.iocoder.yudao.framework.common.util.object.BeanUtils
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageRespVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.*
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO
;
...
...
@@ -41,6 +38,8 @@ import java.net.MalformedURLException;
import
java.util.Collections
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.UUID
;
import
java.util.concurrent.ThreadLocalRandom
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
pojo
.
CommonResult
.
success
;
import
static
cn
.
iocoder
.
yudao
.
framework
.
common
.
util
.
collection
.
CollectionUtils
.
convertSet
;
...
...
@@ -83,13 +82,23 @@ public class AiChatMessageController {
public
Flux
<
CommonResult
<
AiChatMessageSendRespVO
>>
sendChatMessageStream
(
@Valid
@RequestBody
AiChatMessageSendReqVO
sendReqVO
)
throws
MalformedURLException
{
// 禁用ruoyi的上下文能力
sendReqVO
.
setUseContext
(
false
);
String
originalUrl
=
sendReqVO
.
getFileUrl
();
if
(
originalUrl
!=
null
&&
originalUrl
.
contains
(
"218.77.58.8"
)){
// 替换IP地址
String
replacedUrl
=
originalUrl
.
replace
(
"218.77.58.8"
,
"192.168.252.71"
);
sendReqVO
.
setFileUrl
(
replacedUrl
);
List
<
String
>
originalUrls
=
sendReqVO
.
getFileUrl
();
if
(
originalUrls
!=
null
)
{
for
(
int
i
=
0
;
i
<
originalUrls
.
size
();
i
++)
{
String
originalUrl
=
originalUrls
.
get
(
i
);
if
(
originalUrl
!=
null
&&
originalUrl
.
contains
(
"218.77.58.8"
))
{
// 替换IP地址
String
replacedUrl
=
originalUrl
.
replace
(
"218.77.58.8"
,
"192.168.252.71"
);
originalUrls
.
set
(
i
,
replacedUrl
);
// 更新列表中的URL
}
}
sendReqVO
.
setFileUrl
(
originalUrls
);
// 将更新后的列表重新设置到sendReqVO中
}
return
chatMessageService
.
sendChatMessageStream
(
sendReqVO
,
getLoginUserId
());
// 如果 responseChatId 为 null,则随机初始化一个 id
if
(
sendReqVO
.
getResponseChatItemId
()
==
null
)
{
sendReqVO
.
setResponseChatItemId
(
generateBase62UniqueId
(
20
));
}
return
chatMessageService
.
sendChatMessageStream
(
sendReqVO
,
getLoginUserId
(),
originalUrls
);
}
@Operation
(
summary
=
"获得指定对话的消息列表"
)
...
...
@@ -147,4 +156,37 @@ public class AiChatMessageController {
return
success
(
true
);
}
@Operation
(
summary
=
"反馈"
,
description
=
"反馈回复是否有用"
)
@PostMapping
(
"/feedback"
)
@PreAuthorize
(
"@ss.hasPermission('ai:chat-message:update')"
)
public
CommonResult
<
Boolean
>
feedback
(
@Valid
@RequestBody
AiChatMessageFeedBackReqVO
sendReqVO
)
{
chatMessageService
.
updateFeedback
(
sendReqVO
);
return
success
(
true
);
}
private
String
generateBase62UniqueId
(
int
length
)
{
// Base62 字符集(0-9, A-Z, a-z)
final
String
BASE62
=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
;
StringBuilder
sb
=
new
StringBuilder
(
length
);
// 使用 UUID 作为随机源
UUID
uuid
=
UUID
.
randomUUID
();
long
mostSignificantBits
=
uuid
.
getMostSignificantBits
();
long
leastSignificantBits
=
uuid
.
getLeastSignificantBits
();
// 将 UUID 的 128 位数据转换为 Base62
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
// 取随机位并映射到 Base62 字符集
long
randomValue
=
ThreadLocalRandom
.
current
().
nextLong
(
62
);
if
(
i
<
11
)
{
randomValue
=
(
mostSignificantBits
>>>
(
i
*
5
))
&
0x3F
;
// 取 6 位
}
else
{
randomValue
=
(
leastSignificantBits
>>>
((
i
-
11
)
*
5
))
&
0x3F
;
// 取 6 位
}
sb
.
append
(
BASE62
.
charAt
((
int
)
(
randomValue
%
62
)));
}
return
sb
.
toString
();
}
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageFeedBackReqVO.java
0 → 100644
View file @
82c57840
package
cn
.
iocoder
.
yudao
.
module
.
ai
.
controller
.
admin
.
chat
.
vo
.
message
;
import
cn.iocoder.yudao.framework.ai.core.model.fastgpt.FastGPTOptions
;
import
io.swagger.v3.oas.annotations.media.Schema
;
import
jakarta.validation.constraints.NotNull
;
import
lombok.Data
;
import
java.util.List
;
@Schema
(
description
=
"管理后台 - AI 聊天消息反馈"
)
@Data
public
class
AiChatMessageFeedBackReqVO
{
@Schema
(
description
=
"消息编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"1024"
)
@NotNull
(
message
=
"消息编号不能为空"
)
private
Long
id
;
@Schema
(
description
=
"反馈内容"
,
example
=
"回答不准确"
)
// @NotEmpty(message = "聊天内容不能为空")
private
String
fdContent
;
@Schema
(
description
=
"是否有用"
,
example
=
"true"
)
private
Boolean
useful
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageRespVO.java
View file @
82c57840
...
...
@@ -4,6 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import
lombok.Data
;
import
java.time.LocalDateTime
;
import
java.util.List
;
@Schema
(
description
=
"管理后台 - AI 聊天消息 Response VO"
)
@Data
...
...
@@ -47,4 +48,13 @@ public class AiChatMessageRespVO {
@Schema
(
description
=
"角色名字"
,
example
=
"小黄"
)
private
String
roleName
;
@Schema
(
description
=
"对话文件列表"
)
private
List
<
String
>
fileUrls
;
@Schema
(
description
=
"是否有用"
)
private
Boolean
useful
;
@Schema
(
description
=
"反馈内容"
)
private
String
fdContent
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendReqVO.java
View file @
82c57840
...
...
@@ -8,6 +8,8 @@ import jakarta.validation.constraints.Size;
import
lombok.Data
;
import
lombok.experimental.Accessors
;
import
java.util.List
;
@Schema
(
description
=
"管理后台 - AI 聊天消息发送 Request VO"
)
@Data
public
class
AiChatMessageSendReqVO
{
...
...
@@ -23,10 +25,15 @@ public class AiChatMessageSendReqVO {
@Schema
(
description
=
"是否携带上下文"
,
example
=
"true"
)
private
Boolean
useContext
;
// @Schema(description = "文件路径")
// private String fileUrl;
@Schema
(
description
=
"文件路径"
)
private
String
fileUrl
;
private
List
<
String
>
fileUrl
;
@Schema
(
description
=
"变量"
)
private
FastGPTOptions
.
Variables
variables
;
@Schema
(
description
=
"回复信息预设ID"
)
private
String
responseChatItemId
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/vo/message/AiChatMessageSendRespVO.java
View file @
82c57840
...
...
@@ -31,6 +31,9 @@ public class AiChatMessageSendRespVO {
@Schema
(
description
=
"创建时间"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
)
private
LocalDateTime
createTime
;
@Schema
(
description
=
"消息编号"
,
requiredMode
=
Schema
.
RequiredMode
.
REQUIRED
,
example
=
"1024"
)
private
String
chatItemId
;
}
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/dataobject/chat/AiChatMessageDO.java
View file @
82c57840
package
cn
.
iocoder
.
yudao
.
module
.
ai
.
dal
.
dataobject
.
chat
;
import
com.baomidou.mybatisplus.annotation.TableField
;
import
com.baomidou.mybatisplus.annotation.TableId
;
import
com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler
;
import
org.springframework.ai.chat.messages.MessageType
;
import
cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatModelDO
;
...
...
@@ -9,13 +11,15 @@ import com.baomidou.mybatisplus.annotation.KeySequence;
import
com.baomidou.mybatisplus.annotation.TableName
;
import
lombok.*
;
import
java.util.List
;
/**
* AI Chat 消息 DO
*
* @since 2024/4/14 17:35
* @since 2024/4/14 17:35
*/
@TableName
(
"ai_chat_message"
)
@TableName
(
value
=
"ai_chat_message"
,
autoResultMap
=
true
)
@KeySequence
(
"ai_chat_conversation_seq"
)
// 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode
(
callSuper
=
true
)
...
...
@@ -87,4 +91,20 @@ public class AiChatMessageDO extends BaseDO {
*/
private
Boolean
useContext
;
/**
* 文件链接
*/
@TableField
(
typeHandler
=
JacksonTypeHandler
.
class
)
private
List
<
String
>
fileUrls
;
/**
* 是否有用
*/
private
Boolean
useful
;
/**
* 反馈内容
*/
private
String
fdContent
;
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/chat/AiChatMessageMapper.java
View file @
82c57840
...
...
@@ -6,12 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import
cn.iocoder.yudao.framework.common.util.collection.CollectionUtils
;
import
cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX
;
import
cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationPageReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessagePageReqVO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO
;
import
cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO
;
import
com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
org.apache.ibatis.annotations.Mapper
;
import
org.apache.ibatis.annotations.Param
;
import
org.apache.ibatis.annotations.Select
;
import
java.util.Collection
;
import
java.util.Collections
;
...
...
@@ -47,14 +48,31 @@ public interface AiChatMessageMapper extends BaseMapperX<AiChatMessageDO> {
record
->
MapUtil
.
getInt
(
record
,
"count"
));
}
default
PageResult
<
AiChatMessageDO
>
selectPage
(
AiChatMessagePageReqVO
pageReqVO
)
{
return
selectPage
(
pageReqVO
,
new
LambdaQueryWrapperX
<
AiChatMessageDO
>()
.
eqIfPresent
(
AiChatMessageDO:
:
getConversationId
,
pageReqVO
.
getConversationId
())
.
eqIfPresent
(
AiChatMessageDO:
:
getUserId
,
pageReqVO
.
getUserId
())
.
likeIfPresent
(
AiChatMessageDO:
:
getContent
,
pageReqVO
.
getContent
())
.
betweenIfPresent
(
AiChatMessageDO:
:
getCreateTime
,
pageReqVO
.
getCreateTime
())
.
orderByDesc
(
AiChatMessageDO:
:
getId
));
}
// default PageResult<AiChatMessageDO> selectPage(AiChatMessagePageReqVO pageReqVO) {
// return selectPage(pageReqVO, new LambdaQueryWrapperX<AiChatMessageDO>()
// .eqIfPresent(AiChatMessageDO::getConversationId, pageReqVO.getConversationId())
// .eqIfPresent(AiChatMessageDO::getUserId, pageReqVO.getUserId())
// .likeIfPresent(AiChatMessageDO::getContent, pageReqVO.getContent())
// .betweenIfPresent(AiChatMessageDO::getCreateTime, pageReqVO.getCreateTime())
// .orderByDesc(AiChatMessageDO::getId));
// }
/**
* 分页查询,忽略逻辑删除的过滤条件
*/
@Select
({
"<script>"
,
"SELECT * FROM ai_chat_message"
,
"<where>"
,
" <if test='req.conversationId != null'> AND conversation_id = #{req.conversationId} </if>"
,
" <if test='req.userId != null'> AND user_id = #{req.userId} </if>"
,
" <if test='req.content != null'> AND content LIKE CONCAT('%', #{req.content}, '%') </if>"
,
" <if test='req.createTime != null'> AND create_time BETWEEN #{req.createTime[0]} AND #{req.createTime[1]} </if>"
,
"</where>"
,
"ORDER BY id DESC"
,
"</script>"
})
IPage
<
AiChatMessageDO
>
selectPage
(
@Param
(
"page"
)
IPage
<
AiChatMessageDO
>
page
,
@Param
(
"req"
)
AiChatMessagePageReqVO
pageReqVO
);
default
Long
selectCounts
(
Long
conId
){
return
selectCount
(
new
LambdaQueryWrapperX
<
AiChatMessageDO
>()
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatConversationServiceImpl.java
View file @
82c57840
...
...
@@ -169,17 +169,17 @@ public class AiChatConversationServiceImpl implements AiChatConversationService
Assert
.
notNull
(
model
,
"智能体未配置推理模型"
);
validateChatModel
(
model
);
AiChatConversationDO
conversationExist
=
chatConversationMapper
.
selectByRoleAndUserId
(
createReqVO
.
getRoleId
(),
userId
);
if
(
conversationExist
!=
null
){
return
conversationExist
.
getId
();
}
//
AiChatConversationDO conversationExist= chatConversationMapper.selectByRoleAndUserId(createReqVO.getRoleId(), userId);
//
if(conversationExist != null){
//
return conversationExist.getId();
//
}
// 2. 创建 AiChatConversationDO 聊天对话
AiChatConversationDO
conversation
=
new
AiChatConversationDO
().
setUserId
(
userId
).
setPinned
(
false
)
.
setModelId
(
model
.
getId
()).
setModel
(
model
.
getModel
())
.
setTemperature
(
model
.
getTemperature
()).
setMaxTokens
(
model
.
getMaxTokens
()).
setMaxContexts
(
model
.
getMaxContexts
());
if
(
role
!=
null
)
{
conversation
.
setTitle
(
role
.
getName
()).
setRoleId
(
role
.
getId
()).
setSystemMessage
(
role
.
getSystemMessage
());
conversation
.
setTitle
(
createReqVO
.
getFirstMsg
()).
setRoleId
(
role
.
getId
()).
setSystemMessage
(
role
.
getSystemMessage
());
}
else
{
conversation
.
setTitle
(
AiChatConversationDO
.
TITLE_DEFAULT
);
}
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageService.java
View file @
82c57840
...
...
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.ai.service.chat;
import
cn.iocoder.yudao.framework.common.pojo.CommonResult
;
import
cn.iocoder.yudao.framework.common.pojo.PageResult
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageFeedBackReqVO
;
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
;
...
...
@@ -36,7 +37,7 @@ public interface AiChatMessageService {
* @param userId 用户编号
* @return 发送结果
*/
Flux
<
CommonResult
<
AiChatMessageSendRespVO
>>
sendChatMessageStream
(
AiChatMessageSendReqVO
sendReqVO
,
Long
userId
)
throws
MalformedURLException
;
Flux
<
CommonResult
<
AiChatMessageSendRespVO
>>
sendChatMessageStream
(
AiChatMessageSendReqVO
sendReqVO
,
Long
userId
,
List
<
String
>
originalUrls
)
throws
MalformedURLException
;
/**
* 获得指定对话的消息列表
...
...
@@ -62,6 +63,8 @@ public interface AiChatMessageService {
*/
void
deleteChatMessageByConversationId
(
Long
conversationId
,
Long
userId
);
boolean
checkMsgExist
(
Long
conversationId
);
/**
* 【管理员】删除消息
*
...
...
@@ -85,4 +88,5 @@ public interface AiChatMessageService {
*/
PageResult
<
AiChatMessageDO
>
getChatMessagePage
(
AiChatMessagePageReqVO
pageReqVO
);
void
updateFeedback
(
AiChatMessageFeedBackReqVO
sendReqVO
);
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
View file @
82c57840
...
...
@@ -9,8 +9,8 @@ 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.conversation.AiChatConversationRespVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatConversationUpdateMyReqVO
;
import
cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageFeedBackReqVO
;
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
;
...
...
@@ -21,6 +21,8 @@ import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
import
cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants
;
import
cn.iocoder.yudao.module.ai.service.model.AiApiKeyService
;
import
cn.iocoder.yudao.module.ai.service.model.AiChatModelService
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
import
jakarta.annotation.Resource
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.ai.chat.messages.*
;
...
...
@@ -29,8 +31,6 @@ import org.springframework.ai.chat.model.ChatResponse;
import
org.springframework.ai.chat.model.StreamingChatModel
;
import
org.springframework.ai.chat.prompt.ChatOptions
;
import
org.springframework.ai.chat.prompt.Prompt
;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.core.io.FileUrlResource
;
import
org.springframework.stereotype.Service
;
import
org.springframework.transaction.annotation.Transactional
;
import
org.springframework.util.MimeTypeUtils
;
...
...
@@ -81,11 +81,11 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 插入 user 发送消息
AiChatMessageDO
userMessage
=
createChatMessage
(
conversation
.
getId
(),
null
,
model
,
userId
,
conversation
.
getRoleId
(),
MessageType
.
USER
,
sendReqVO
.
getContent
(),
sendReqVO
.
getUseContext
());
userId
,
conversation
.
getRoleId
(),
MessageType
.
USER
,
sendReqVO
.
getContent
(),
sendReqVO
.
getUseContext
()
,
sendReqVO
.
getFileUrl
()
);
// 3.1 插入 assistant 接收消息
AiChatMessageDO
assistantMessage
=
createChatMessage
(
conversation
.
getId
(),
userMessage
.
getId
(),
model
,
userId
,
conversation
.
getRoleId
(),
MessageType
.
ASSISTANT
,
""
,
sendReqVO
.
getUseContext
());
userId
,
conversation
.
getRoleId
(),
MessageType
.
ASSISTANT
,
""
,
sendReqVO
.
getUseContext
()
,
sendReqVO
.
getFileUrl
()
);
// 3.2 创建 chat 需要的 Prompt
Prompt
prompt
=
buildPrompt
(
conversation
,
historyMessages
,
model
,
sendReqVO
);
...
...
@@ -99,7 +99,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
}
@Override
public
Flux
<
CommonResult
<
AiChatMessageSendRespVO
>>
sendChatMessageStream
(
AiChatMessageSendReqVO
sendReqVO
,
Long
userId
)
throws
MalformedURLException
{
public
Flux
<
CommonResult
<
AiChatMessageSendRespVO
>>
sendChatMessageStream
(
AiChatMessageSendReqVO
sendReqVO
,
Long
userId
,
List
<
String
>
originalUrls
)
throws
MalformedURLException
{
// 1.1 校验对话存在
AiChatConversationDO
conversation
=
chatConversationService
.
validateChatConversationExists
(
sendReqVO
.
getConversationId
());
if
(
ObjUtil
.
notEqual
(
conversation
.
getUserId
(),
userId
))
{
...
...
@@ -112,13 +112,14 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 插入 user 发送消息
Long
count
=
chatMessageMapper
.
selectCounts
(
conversation
.
getId
());
if
(
count
==
0
&&
Objects
.
equals
(
conversation
.
getTitle
(),
AiChatConversationDO
.
TITLE_DEFAULT
)){
if
(
count
==
0
){
// if(count == 0 && Objects.equals(conversation.getTitle(), AiChatConversationDO.TITLE_DEFAULT)){
AiChatConversationUpdateMyReqVO
updateMyReq
=
BeanUtils
.
toBean
(
conversation
,
AiChatConversationUpdateMyReqVO
.
class
);
updateMyReq
.
setTitle
(
sendReqVO
.
getContent
());
chatConversationService
.
updateChatConversationMy
(
updateMyReq
,
userId
);
}
AiChatMessageDO
userMessage
=
createChatMessage
(
conversation
.
getId
(),
null
,
model
,
userId
,
conversation
.
getRoleId
(),
MessageType
.
USER
,
sendReqVO
.
getContent
(),
sendReqVO
.
getUseContext
());
userId
,
conversation
.
getRoleId
(),
MessageType
.
USER
,
sendReqVO
.
getContent
(),
sendReqVO
.
getUseContext
()
,
originalUrls
);
// 3.1 插入 assistant 接收消息
// AiChatMessageDO assistantMessage = createChatMessage(conversation.getId(), userMessage.getId(), model,
...
...
@@ -141,7 +142,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
contentBuffer
.
append
(
newContent
);
// 响应结果
return
success
(
new
AiChatMessageSendRespVO
().
setSend
(
BeanUtils
.
toBean
(
userMessage
,
AiChatMessageSendRespVO
.
Message
.
class
))
.
setReceive
(
BeanUtils
.
toBean
(
assistantMessage
,
AiChatMessageSendRespVO
.
Message
.
class
).
setContent
(
newContent
)));
.
setReceive
(
BeanUtils
.
toBean
(
assistantMessage
,
AiChatMessageSendRespVO
.
Message
.
class
).
setContent
(
newContent
)
.
setChatItemId
(
sendReqVO
.
getResponseChatItemId
())
));
}).
doOnComplete
(()
->
{
// 忽略租户,因为 Flux 异步无法透传租户
// TenantUtils.executeIgnore(() -> chatMessageMapper.updateById(new AiChatMessageDO().setId(assistantMessage.getId()).setContent(contentBuffer.toString())));
...
...
@@ -174,8 +175,18 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
contextMessages
.
forEach
(
message
->
chatMessages
.
add
(
AiUtils
.
buildMessage
(
message
.
getType
(),
message
.
getContent
())));
// 1.3 user message 新发送消息
UserMessage
send_message
;
if
(
sendReqVO
.
getFileUrl
()
!=
null
&&
!
Objects
.
equals
(
sendReqVO
.
getFileUrl
(),
""
)){
send_message
=
new
UserMessage
(
sendReqVO
.
getContent
(),
new
Media
(
MimeTypeUtils
.
TEXT_PLAIN
,
new
URL
(
sendReqVO
.
getFileUrl
())));
if
(
sendReqVO
.
getFileUrl
()
!=
null
&&
!
sendReqVO
.
getFileUrl
().
isEmpty
()){
List
<
Media
>
mediaList
=
new
ArrayList
<>();
for
(
String
fileUrl
:
sendReqVO
.
getFileUrl
())
{
try
{
mediaList
.
add
(
new
Media
(
MimeTypeUtils
.
TEXT_PLAIN
,
new
URL
(
fileUrl
)));
}
catch
(
MalformedURLException
e
)
{
// 处理URL异常
e
.
printStackTrace
();
}
}
send_message
=
new
UserMessage
(
sendReqVO
.
getContent
(),
mediaList
);
}
else
{
send_message
=
new
UserMessage
(
sendReqVO
.
getContent
());
}
...
...
@@ -185,7 +196,7 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
// 2. 构建 ChatOptions 对象
AiPlatformEnum
platform
=
AiPlatformEnum
.
validatePlatform
(
model
.
getPlatform
());
ChatOptions
chatOptions
=
AiUtils
.
buildChatOptions
(
platform
,
model
.
getModel
(),
conversation
.
getTemperature
(),
conversation
.
getMaxTokens
(),
String
.
valueOf
(
conversation
.
getId
()),
sendReqVO
.
getVariables
());
conversation
.
getTemperature
(),
conversation
.
getMaxTokens
(),
String
.
valueOf
(
conversation
.
getId
()),
sendReqVO
.
getVariables
()
,
sendReqVO
.
getResponseChatItemId
()
);
return
new
Prompt
(
chatMessages
,
chatOptions
);
}
...
...
@@ -230,10 +241,10 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
private
AiChatMessageDO
createChatMessage
(
Long
conversationId
,
Long
replyId
,
AiChatModelDO
model
,
Long
userId
,
Long
roleId
,
MessageType
messageType
,
String
content
,
Boolean
useContext
)
{
MessageType
messageType
,
String
content
,
Boolean
useContext
,
List
<
String
>
fileUrls
)
{
AiChatMessageDO
message
=
new
AiChatMessageDO
().
setConversationId
(
conversationId
).
setReplyId
(
replyId
)
.
setModel
(
model
.
getModel
()).
setModelId
(
model
.
getId
()).
setUserId
(
userId
).
setRoleId
(
roleId
)
.
setType
(
messageType
.
getValue
()).
setContent
(
content
).
setUseContext
(
useContext
);
.
setType
(
messageType
.
getValue
()).
setContent
(
content
).
setUseContext
(
useContext
)
.
setFileUrls
(
fileUrls
)
;
message
.
setCreateTime
(
LocalDateTime
.
now
());
chatMessageMapper
.
insert
(
message
);
return
message
;
...
...
@@ -267,6 +278,13 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
}
@Override
public
boolean
checkMsgExist
(
Long
conversationId
)
{
// 1. 校验消息存在
List
<
AiChatMessageDO
>
messages
=
chatMessageMapper
.
selectListByConversationId
(
conversationId
);
return
CollUtil
.
isEmpty
(
messages
);
}
@Override
public
void
deleteChatMessageByAdmin
(
Long
id
)
{
// 1. 校验消息存在
AiChatMessageDO
message
=
chatMessageMapper
.
selectById
(
id
);
...
...
@@ -284,7 +302,26 @@ public class AiChatMessageServiceImpl implements AiChatMessageService {
@Override
public
PageResult
<
AiChatMessageDO
>
getChatMessagePage
(
AiChatMessagePageReqVO
pageReqVO
)
{
return
chatMessageMapper
.
selectPage
(
pageReqVO
);
// return chatMessageMapper.selectPage(pageReqVO);
// 创建分页对象
IPage
<
AiChatMessageDO
>
page
=
new
Page
<>(
pageReqVO
.
getPageNo
(),
pageReqVO
.
getPageSize
());
// 调用 Mapper 方法
IPage
<
AiChatMessageDO
>
resultPage
=
chatMessageMapper
.
selectPage
(
page
,
pageReqVO
);
// 转换为 PageResult
return
new
PageResult
<>(
resultPage
.
getRecords
(),
resultPage
.
getTotal
());
}
@Override
public
void
updateFeedback
(
AiChatMessageFeedBackReqVO
sendReqVO
)
{
// 1. 校验消息存在
AiChatMessageDO
message
=
chatMessageMapper
.
selectById
(
sendReqVO
.
getId
());
if
(
message
==
null
)
{
throw
exception
(
CHAT_MESSAGE_NOT_EXIST
);
}
// 2. 执行更新
message
.
setUseful
(
sendReqVO
.
getUseful
());
message
.
setFdContent
(
sendReqVO
.
getFdContent
());
chatMessageMapper
.
updateById
(
message
);
}
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/mindmap/AiMindMapServiceImpl.java
View file @
82c57840
...
...
@@ -108,7 +108,7 @@ public class AiMindMapServiceImpl implements AiMindMapService {
List
<
Message
>
chatMessages
=
buildMessages
(
generateReqVO
,
systemMessage
);
// 2. 构建 options 对象
AiPlatformEnum
platform
=
AiPlatformEnum
.
validatePlatform
(
model
.
getPlatform
());
ChatOptions
options
=
AiUtils
.
buildChatOptions
(
platform
,
model
.
getModel
(),
model
.
getTemperature
(),
model
.
getMaxTokens
(),
""
,
null
);
ChatOptions
options
=
AiUtils
.
buildChatOptions
(
platform
,
model
.
getModel
(),
model
.
getTemperature
(),
model
.
getMaxTokens
(),
""
,
null
,
""
);
return
new
Prompt
(
chatMessages
,
options
);
}
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
View file @
82c57840
...
...
@@ -126,7 +126,7 @@ public class AiWriteServiceImpl implements AiWriteService {
List
<
Message
>
chatMessages
=
buildMessages
(
generateReqVO
,
systemMessage
);
// 2. 构建 options 对象
AiPlatformEnum
platform
=
AiPlatformEnum
.
validatePlatform
(
model
.
getPlatform
());
ChatOptions
options
=
AiUtils
.
buildChatOptions
(
platform
,
model
.
getModel
(),
model
.
getTemperature
(),
model
.
getMaxTokens
(),
""
,
null
);
ChatOptions
options
=
AiUtils
.
buildChatOptions
(
platform
,
model
.
getModel
(),
model
.
getTemperature
(),
model
.
getMaxTokens
(),
""
,
null
,
""
);
return
new
Prompt
(
chatMessages
,
options
);
}
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTApi.java
View file @
82c57840
...
...
@@ -113,28 +113,28 @@ public class FastGPTApi {
}
@JsonInclude
(
Include
.
NON_NULL
)
public
static
record
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
String
chatId
,
FastGPTOptions
.
Variables
variables
,
Float
frequencyPenalty
,
Map
<
String
,
Integer
>
logitBias
,
Boolean
logprobs
,
Integer
topLogprobs
,
Integer
maxTokens
,
Integer
n
,
Float
presencePenalty
,
ResponseFormat
responseFormat
,
Integer
seed
,
List
<
String
>
stop
,
Boolean
stream
,
Float
temperature
,
Float
topP
,
List
<
FunctionTool
>
tools
,
Object
toolChoice
,
String
user
)
{
public
static
record
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
String
chatId
,
FastGPTOptions
.
Variables
variables
,
String
responseChatItemId
,
Float
frequencyPenalty
,
Map
<
String
,
Integer
>
logitBias
,
Boolean
logprobs
,
Integer
topLogprobs
,
Integer
maxTokens
,
Integer
n
,
Float
presencePenalty
,
ResponseFormat
responseFormat
,
Integer
seed
,
List
<
String
>
stop
,
Boolean
stream
,
Float
temperature
,
Float
topP
,
List
<
FunctionTool
>
tools
,
Object
toolChoice
,
String
user
)
{
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
Float
temperature
)
{
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
false
,
temperature
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
String
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
false
,
temperature
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
}
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
Float
temperature
,
boolean
stream
)
{
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
temperature
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
String
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
temperature
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
}
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
List
<
FunctionTool
>
tools
,
Object
toolChoice
)
{
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
false
,
0.8
F
,
(
Float
)
null
,
tools
,
toolChoice
,
(
String
)
null
);
this
(
messages
,
model
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
String
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
false
,
0.8
F
,
(
Float
)
null
,
tools
,
toolChoice
,
(
String
)
null
);
}
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
Boolean
stream
)
{
this
(
messages
,
(
String
)
null
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
(
Float
)
null
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
this
(
messages
,
(
String
)
null
,
(
String
)
null
,
(
FastGPTOptions
.
Variables
)
null
,
(
String
)
null
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
(
Float
)
null
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
}
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
String
chatId
,
FastGPTOptions
.
Variables
variables
,
Boolean
stream
)
{
this
(
messages
,
model
,
chatId
,
variables
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
(
Float
)
null
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
public
ChatCompletionRequest
(
List
<
ChatCompletionMessage
>
messages
,
String
model
,
String
chatId
,
FastGPTOptions
.
Variables
variables
,
String
responseChatItemId
,
Boolean
stream
)
{
this
(
messages
,
model
,
chatId
,
variables
,
responseChatItemId
,
(
Float
)
null
,
(
Map
)
null
,
(
Boolean
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Integer
)
null
,
(
Float
)
null
,
(
ResponseFormat
)
null
,
(
Integer
)
null
,
(
List
)
null
,
stream
,
(
Float
)
null
,
(
Float
)
null
,
(
List
)
null
,
(
Object
)
null
,
(
String
)
null
);
}
public
ChatCompletionRequest
(
@JsonProperty
(
"messages"
)
List
<
ChatCompletionMessage
>
messages
,
@JsonProperty
(
"model"
)
String
model
,
@JsonProperty
(
"chatId"
)
String
chatId
,
@JsonProperty
(
"variables"
)
FastGPTOptions
.
Variables
variables
,
@JsonProperty
(
"frequency_penalty"
)
Float
frequencyPenalty
,
@JsonProperty
(
"logit_bias"
)
Map
<
String
,
Integer
>
logitBias
,
@JsonProperty
(
"logprobs"
)
Boolean
logprobs
,
@JsonProperty
(
"top_logprobs"
)
Integer
topLogprobs
,
@JsonProperty
(
"max_tokens"
)
Integer
maxTokens
,
@JsonProperty
(
"n"
)
Integer
n
,
@JsonProperty
(
"presence_penalty"
)
Float
presencePenalty
,
@JsonProperty
(
"response_format"
)
ResponseFormat
responseFormat
,
@JsonProperty
(
"seed"
)
Integer
seed
,
@JsonProperty
(
"stop"
)
List
<
String
>
stop
,
@JsonProperty
(
"stream"
)
Boolean
stream
,
@JsonProperty
(
"temperature"
)
Float
temperature
,
@JsonProperty
(
"top_p"
)
Float
topP
,
@JsonProperty
(
"tools"
)
List
<
FunctionTool
>
tools
,
@JsonProperty
(
"tool_choice"
)
Object
toolChoice
,
@JsonProperty
(
"user"
)
String
user
)
{
public
ChatCompletionRequest
(
@JsonProperty
(
"messages"
)
List
<
ChatCompletionMessage
>
messages
,
@JsonProperty
(
"model"
)
String
model
,
@JsonProperty
(
"chatId"
)
String
chatId
,
@JsonProperty
(
"variables"
)
FastGPTOptions
.
Variables
variables
,
@JsonProperty
(
"
responseChatItemId"
)
String
responseChatItemId
,
@JsonProperty
(
"
frequency_penalty"
)
Float
frequencyPenalty
,
@JsonProperty
(
"logit_bias"
)
Map
<
String
,
Integer
>
logitBias
,
@JsonProperty
(
"logprobs"
)
Boolean
logprobs
,
@JsonProperty
(
"top_logprobs"
)
Integer
topLogprobs
,
@JsonProperty
(
"max_tokens"
)
Integer
maxTokens
,
@JsonProperty
(
"n"
)
Integer
n
,
@JsonProperty
(
"presence_penalty"
)
Float
presencePenalty
,
@JsonProperty
(
"response_format"
)
ResponseFormat
responseFormat
,
@JsonProperty
(
"seed"
)
Integer
seed
,
@JsonProperty
(
"stop"
)
List
<
String
>
stop
,
@JsonProperty
(
"stream"
)
Boolean
stream
,
@JsonProperty
(
"temperature"
)
Float
temperature
,
@JsonProperty
(
"top_p"
)
Float
topP
,
@JsonProperty
(
"tools"
)
List
<
FunctionTool
>
tools
,
@JsonProperty
(
"tool_choice"
)
Object
toolChoice
,
@JsonProperty
(
"user"
)
String
user
)
{
this
.
messages
=
messages
;
this
.
model
=
model
;
this
.
chatId
=
chatId
;
...
...
@@ -155,6 +155,7 @@ public class FastGPTApi {
this
.
tools
=
tools
;
this
.
toolChoice
=
toolChoice
;
this
.
user
=
user
;
this
.
responseChatItemId
=
responseChatItemId
;
}
@JsonProperty
(
"messages"
)
...
...
@@ -177,6 +178,11 @@ public class FastGPTApi {
return
this
.
variables
;
}
@JsonProperty
(
"responseChatItemId"
)
public
String
responseChatItemId
()
{
return
this
.
responseChatItemId
;
}
@JsonProperty
(
"frequency_penalty"
)
public
Float
frequencyPenalty
()
{
return
this
.
frequencyPenalty
;
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTChatModel.java
View file @
82c57840
...
...
@@ -164,7 +164,7 @@ public class FastGPTChatModel extends AbstractFunctionCallSupport<FastGPTApi.Cha
Set
<
String
>
promptEnabledFunctions
=
this
.
handleFunctionCallbackConfigurations
(
updatedRuntimeOptions
,
true
);
functionsForThisRequest
.
addAll
(
promptEnabledFunctions
);
// request = (FastGPTApi.ChatCompletionRequest)ModelOptionsUtils.merge(updatedRuntimeOptions, request, FastGPTApi.ChatCompletionRequest.class);
request
=
new
FastGPTApi
.
ChatCompletionRequest
(
chatCompletionMessages
,
updatedRuntimeOptions
.
getModel
(),
updatedRuntimeOptions
.
getChatId
(),
updatedRuntimeOptions
.
getVariables
(),
stream
);
request
=
new
FastGPTApi
.
ChatCompletionRequest
(
chatCompletionMessages
,
updatedRuntimeOptions
.
getModel
(),
updatedRuntimeOptions
.
getChatId
(),
updatedRuntimeOptions
.
getVariables
(),
updatedRuntimeOptions
.
getResponseChatItemId
(),
stream
);
}
// if (this.defaultOptions != null) {
...
...
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/model/fastgpt/FastGPTOptions.java
View file @
82c57840
...
...
@@ -65,6 +65,9 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
@JsonIgnore
private
Set
<
String
>
functions
=
new
HashSet
();
@JsonProperty
(
"responseChatItemId"
)
private
String
responseChatItemId
;
@JsonInclude
(
Include
.
NON_NULL
)
public
static
record
Variables
(
String
scenarios
)
{
public
Variables
(
@JsonProperty
(
"scenarios"
)
String
scenarios
)
{
...
...
@@ -108,6 +111,14 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
this
.
chatId
=
chatId
;
}
public
String
getResponseChatItemId
()
{
return
this
.
responseChatItemId
;
}
public
void
setResponseChatItemId
(
String
responseChatItemId
)
{
this
.
responseChatItemId
=
responseChatItemId
;
}
public
Float
getFrequencyPenalty
()
{
return
this
.
frequencyPenalty
;
}
...
...
@@ -249,6 +260,7 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
int
result
=
1
;
result
=
31
*
result
+
(
this
.
model
==
null
?
0
:
this
.
model
.
hashCode
());
result
=
31
*
result
+
(
this
.
chatId
==
null
?
0
:
this
.
chatId
.
hashCode
());
result
=
31
*
result
+
(
this
.
responseChatItemId
==
null
?
0
:
this
.
responseChatItemId
.
hashCode
());
result
=
31
*
result
+
(
this
.
frequencyPenalty
==
null
?
0
:
this
.
frequencyPenalty
.
hashCode
());
result
=
31
*
result
+
(
this
.
logitBias
==
null
?
0
:
this
.
logitBias
.
hashCode
());
result
=
31
*
result
+
(
this
.
logprobs
==
null
?
0
:
this
.
logprobs
.
hashCode
());
...
...
@@ -290,6 +302,13 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
}
else
if
(!
this
.
chatId
.
equals
(
other
.
chatId
))
{
return
false
;
}
if
(
this
.
responseChatItemId
==
null
)
{
if
(
other
.
responseChatItemId
!=
null
)
{
return
false
;
}
}
else
if
(!
this
.
responseChatItemId
.
equals
(
other
.
responseChatItemId
))
{
return
false
;
}
if
(
this
.
frequencyPenalty
==
null
)
{
if
(
other
.
frequencyPenalty
!=
null
)
{
...
...
@@ -555,5 +574,10 @@ public class FastGPTOptions implements FunctionCallingOptions, ChatOptions {
public
FastGPTOptions
build
()
{
return
this
.
options
;
}
public
Builder
withChatItemId
(
String
responseChatItemId
)
{
this
.
options
.
responseChatItemId
=
responseChatItemId
;
return
this
;
}
}
}
ruoyi-vue-pro-master-jdk17/yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
View file @
82c57840
...
...
@@ -21,7 +21,7 @@ import org.springframework.ai.zhipuai.ZhiPuAiChatOptions;
*/
public
class
AiUtils
{
public
static
ChatOptions
buildChatOptions
(
AiPlatformEnum
platform
,
String
model
,
Double
temperature
,
Integer
maxTokens
,
String
chatId
,
FastGPTOptions
.
Variables
variables
)
{
public
static
ChatOptions
buildChatOptions
(
AiPlatformEnum
platform
,
String
model
,
Double
temperature
,
Integer
maxTokens
,
String
chatId
,
FastGPTOptions
.
Variables
variables
,
String
chatItemId
)
{
Float
temperatureF
=
temperature
!=
null
?
temperature
.
floatValue
()
:
null
;
//noinspection EnhancedSwitchMigration
switch
(
platform
)
{
...
...
@@ -43,7 +43,7 @@ public class AiUtils {
case
OLLAMA:
return
OllamaOptions
.
create
().
withModel
(
model
).
withTemperature
(
temperatureF
).
withNumPredict
(
maxTokens
);
case
FAST_GPT:
return
FastGPTOptions
.
builder
().
withModel
(
model
).
withTemperature
(
temperatureF
).
withMaxTokens
(
maxTokens
).
withChatId
(
chatId
).
withVariables
(
variables
).
build
();
return
FastGPTOptions
.
builder
().
withModel
(
model
).
withTemperature
(
temperatureF
).
withMaxTokens
(
maxTokens
).
withChatId
(
chatId
).
withVariables
(
variables
).
withChatItemId
(
chatItemId
).
build
();
default
:
throw
new
IllegalArgumentException
(
StrUtil
.
format
(
"未知平台({})"
,
platform
));
}
...
...
ruoyi-vue-pro-master-jdk17/yudao-server/.DS_Store
0 → 100644
View file @
82c57840
File added
ruoyi-vue-pro-master-jdk17/yudao-server/src/main/resources/application.yaml
View file @
82c57840
...
...
@@ -75,6 +75,7 @@ mybatis-plus:
# id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
logic-delete-value
:
1
# 逻辑已删除值(默认为 1)
logic-not-delete-value
:
0
# 逻辑未删除值(默认为 0)
logic-delete-field
:
deleted
# 逻辑删除字段名
banner
:
false
# 关闭控制台的 Banner 打印
type-aliases-package
:
${yudao.info.base-package}.module.*.dal.dataobject
encryptor
:
...
...
yudao-ui-admin-vue3/.DS_Store
0 → 100644
View file @
82c57840
File added
yudao-ui-admin-vue3/src/api/ai/chat/message/index.ts
View file @
82c57840
...
...
@@ -17,6 +17,8 @@ export interface ChatMessageVO {
createTime
:
Date
// 创建时间
roleAvatar
:
string
// 角色头像
userAvatar
:
string
// 创建时间
useful
:
boolean
// 是否有用
fdContent
:
boolean
// 反馈内容
}
// AI chat 聊天
...
...
yudao-ui-admin-vue3/src/types/auto-components.d.ts
View file @
82c57840
...
...
@@ -10,6 +10,8 @@ declare module 'vue' {
AddNode
:
typeof
import
(
'./../components/SimpleProcessDesigner/src/addNode.vue'
)[
'default'
]
AppLinkInput
:
typeof
import
(
'./../components/AppLinkInput/index.vue'
)[
'default'
]
AppLinkSelectDialog
:
typeof
import
(
'./../components/AppLinkInput/AppLinkSelectDialog.vue'
)[
'default'
]
'AutoComponents.d'
:
typeof
import
(
'./auto-components.d.ts'
)[
'default'
]
'AutoImports.d'
:
typeof
import
(
'./auto-imports.d.ts'
)[
'default'
]
Backtop
:
typeof
import
(
'./../components/Backtop/src/Backtop.vue'
)[
'default'
]
CardTitle
:
typeof
import
(
'./../components/Card/src/CardTitle.vue'
)[
'default'
]
ColorInput
:
typeof
import
(
'./../components/ColorInput/index.vue'
)[
'default'
]
...
...
yudao-ui-admin-vue3/src/views/ai/chat/manager/ChatMessageList.vue
View file @
82c57840
...
...
@@ -83,6 +83,12 @@
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.useContext"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"是否有用"
align=
"center"
prop=
"useful"
width=
"100"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.INFRA_BOOLEAN_STRING"
:value=
"scope.row.useful"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"反馈内容"
align=
"center"
prop=
"fdContent"
width=
"300"
/>
<el-table-column
label=
"操作"
align=
"center"
fixed=
"right"
>
<
template
#
default=
"scope"
>
<el-button
...
...
yudao-ui-admin-vue3/src/views/infra/file/FileForm.vue
View file @
82c57840
...
...
@@ -13,14 +13,14 @@
:on-exceed=
"handleExceed"
:on-success=
"submitFormSuccess"
:http-request=
"httpRequest"
accept=
"
.jpg, .png, .gif
"
accept=
""
drag
>
<i
class=
"el-icon-upload"
></i>
<div
class=
"el-upload__text"
>
将文件拖到此处,或
<em>
点击上传
</em></div>
<template
#
tip
>
<div
class=
"el-upload__tip"
style=
"color: red"
>
提示:
仅允许导入 jpg、png、gif 格式文件
!
提示:
文件大小低于64M
!
</div>
</
template
>
</el-upload>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment