1 package org.onap.usecaseui.llmadaptation.service.impl;
3 import com.alibaba.fastjson2.JSON;
4 import com.alibaba.fastjson2.JSONArray;
5 import com.alibaba.fastjson2.JSONObject;
6 import lombok.extern.slf4j.Slf4j;
7 import org.jetbrains.annotations.NotNull;
8 import org.onap.usecaseui.llmadaptation.bean.*;
9 import org.onap.usecaseui.llmadaptation.bean.fastgpt.dataset.CreateCollectionParam;
10 import org.onap.usecaseui.llmadaptation.bean.fastgpt.dataset.CreateDataSetParam;
11 import org.onap.usecaseui.llmadaptation.bean.fastgpt.dataset.CreateDataSetResponse;
12 import org.onap.usecaseui.llmadaptation.constant.CommonConstant;
13 import org.onap.usecaseui.llmadaptation.constant.FastGptConstant;
14 import org.onap.usecaseui.llmadaptation.mapper.DatasetMapper;
15 import org.onap.usecaseui.llmadaptation.service.FastGptDatasetService;
16 import org.onap.usecaseui.llmadaptation.util.TimeUtil;
17 import org.springframework.beans.factory.annotation.Autowired;
18 import org.springframework.core.io.buffer.DataBuffer;
19 import org.springframework.http.ContentDisposition;
20 import org.springframework.http.MediaType;
21 import org.springframework.http.client.MultipartBodyBuilder;
22 import org.springframework.http.codec.multipart.FilePart;
23 import org.springframework.stereotype.Service;
24 import org.springframework.web.reactive.function.BodyInserters;
25 import org.springframework.web.reactive.function.client.WebClient;
26 import reactor.core.publisher.Flux;
27 import reactor.core.publisher.Mono;
30 import java.util.List;
32 import java.util.stream.Collectors;
33 import java.util.stream.IntStream;
35 import static org.springframework.http.MediaType.APPLICATION_JSON;
39 public class FastGptDatasetServiceImpl implements FastGptDatasetService {
41 private DatasetMapper datasetMapper;
44 private WebClient webClient;
47 public Mono<ServiceResult> createDataset(Flux<FilePart> fileParts, String metaData, MaaSPlatform maaSPlatform) {
48 KnowledgeBase knowledgeBase = JSONObject.parseObject(metaData, KnowledgeBase.class);
49 knowledgeBase.setUpdateTime(TimeUtil.getNowTime());
50 CreateDataSetParam dataSetParam = new CreateDataSetParam();
51 dataSetParam.setAgentModel(maaSPlatform.getVectorModel());
52 dataSetParam.setType("dataset");
53 dataSetParam.setIntro(knowledgeBase.getKnowledgeBaseDescription());
54 dataSetParam.setName(knowledgeBase.getKnowledgeBaseName());
55 return webClient.post()
56 .uri(maaSPlatform.getServerIp() + FastGptConstant.CREATE_DATASET_URL)
57 .contentType(APPLICATION_JSON)
58 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
59 .bodyValue(dataSetParam)
61 .bodyToMono(CreateDataSetResponse.class)
62 .flatMap(response -> {
63 if (response.getCode() == 200) {
64 String knowledgeBaseId = String.valueOf(response.getData());
66 .flatMap(filePart -> uploadFile(filePart, knowledgeBaseId, maaSPlatform.getServerIp()))
67 .then(Mono.defer(() -> {
68 knowledgeBase.setKnowledgeBaseId(knowledgeBaseId);
69 datasetMapper.insertKnowledgeBaseRecord(knowledgeBase);
70 return handleFileId(knowledgeBaseId, maaSPlatform.getServerIp());
73 log.error("Error occurred during file upload: {}", e.getMessage());
74 return Mono.just(new ServiceResult(new ResultHeader(500, "file upload failed")));
77 return Mono.just(new ServiceResult(new ResultHeader(500, response.getMessage())));
81 log.error("Error occurred while creating dataset: {}", e.getMessage());
82 return Mono.just(new ServiceResult(new ResultHeader(500, "create failed")));
86 private Mono<ServiceResult> handleFileId(String knowledgeBaseId, String serverIp) {
87 JSONObject jsonObject = new JSONObject();
88 jsonObject.put("datasetId", knowledgeBaseId);
89 return webClient.post()
90 .uri(serverIp + FastGptConstant.GET_COLLECTION_LIST_URL)
91 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
92 .bodyValue(jsonObject)
94 .bodyToMono(CreateDataSetResponse.class)
95 .flatMap(response -> {
96 Object data = response.getData();
97 JSONArray jsonArray = JSONObject.parseObject(JSONObject.toJSONString(data)).getJSONArray("data");
98 Map<String, String> resultMap = IntStream.range(0, jsonArray.size())
99 .mapToObj(jsonArray::getJSONObject)
100 .collect(Collectors.toMap(
101 obj -> obj.getString("fileId"),
102 obj -> obj.getString("_id")
104 List<File> fileList = datasetMapper.getFileNamesByKnowledgeBaseId(knowledgeBaseId);
105 List<File> updatedFileList = fileList.stream()
106 .map(file -> new File(
107 resultMap.getOrDefault(file.getFileId(), file.getFileId()),
110 datasetMapper.deleteFileById(knowledgeBaseId);
111 datasetMapper.insertFileName(updatedFileList, knowledgeBaseId);
112 return Mono.just(new ServiceResult(new ResultHeader(200, "create success")));
116 private Mono<Void> uploadFile(FilePart filePart, String knowledgeBaseId, String serverIp) {
117 String filename = filePart.filename();
118 Flux<DataBuffer> content = filePart.content();
120 MultipartBodyBuilder builder = new MultipartBodyBuilder();
121 builder.part("metadata", "", APPLICATION_JSON);
122 builder.part("bucketName", "dataset");
123 builder.asyncPart("file", content, DataBuffer.class)
124 .headers(headers -> {
125 ContentDisposition contentDisposition = ContentDisposition
126 .builder("form-data")
130 headers.setContentDisposition(contentDisposition);
131 headers.setContentType(MediaType.TEXT_PLAIN);
134 return webClient.post()
135 .uri(serverIp + FastGptConstant.UPLOAD_FILE_URL)
136 .contentType(MediaType.MULTIPART_FORM_DATA)
137 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
138 .body(BodyInserters.fromMultipartData(builder.build()))
140 .bodyToMono(CreateDataSetResponse.class)
141 .flatMap(response -> {
142 if (response.getCode() != 200) {
143 log.error("response is {}", response);
146 Object data = response.getData();
147 JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(data));
148 String fileId = jsonObject.getString("fileId");
149 CreateCollectionParam createCollectionParam = getCreateCollectionParam(knowledgeBaseId, fileId, filename);
151 return webClient.post()
152 .uri(serverIp + FastGptConstant.CRATE_COLLECTION_URL)
153 .contentType(APPLICATION_JSON)
154 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
155 .bodyValue(createCollectionParam)
157 .bodyToMono(CreateDataSetResponse.class)
158 .flatMap(responseData -> {
159 if (responseData.getCode() == 200) {
160 File file = new File(String.valueOf(fileId), filename);
161 datasetMapper.insertFileName(List.of(file), String.valueOf(knowledgeBaseId));
169 private static CreateCollectionParam getCreateCollectionParam(String knowledgeBaseId, String fileId, String fileName) {
170 CreateCollectionParam createCollectionParam = new CreateCollectionParam();
171 createCollectionParam.setTrainingType("chunk");
172 createCollectionParam.setDatasetId(knowledgeBaseId);
173 createCollectionParam.setChunkSize(700);
174 createCollectionParam.setChunkSplitter("");
175 createCollectionParam.setFileId(fileId);
176 createCollectionParam.setName(fileName);
177 createCollectionParam.setQaPrompt("");
178 return createCollectionParam;
182 public Mono<ServiceResult> removeDataset(String knowledgeBaseId, String serverIp) {
183 String url = serverIp + FastGptConstant.DELETE_DATASET_URL + knowledgeBaseId;
184 return webClient.delete()
186 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
188 .bodyToMono(CreateDataSetResponse.class)
189 .flatMap(response -> {
190 if (response.getCode() == 200) {
191 return Mono.fromRunnable(() -> {
193 datasetMapper.deleteKnowledgeBaseByUuid(knowledgeBaseId);
194 datasetMapper.deleteFileById(knowledgeBaseId);
195 } catch (Exception dbException) {
196 throw new RuntimeException("Database operation failed", dbException);
198 }).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete success"))));
200 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
203 .onErrorResume(e -> {
204 log.error("Error occurred while delete dataset: {}", e.getMessage());
205 return Mono.just(new ServiceResult(new ResultHeader(500, "delete failed")));
210 public Mono<ServiceResult> editDataset(KnowledgeBase knowledgeBase, MaaSPlatform maaSPlatform) {
211 KnowledgeBase knowledgeBaseRecordById = datasetMapper.getKnowledgeBaseRecordById(knowledgeBase.getKnowledgeBaseId());
212 if (knowledgeBaseRecordById == null) {
213 return Mono.just(new ServiceResult(new ResultHeader(500, "dataset is not exist")));
215 JSONObject updateParam = new JSONObject();
216 updateParam.put("id", knowledgeBase.getKnowledgeBaseId());
217 updateParam.put("name", knowledgeBase.getKnowledgeBaseName());
218 updateParam.put("intro", knowledgeBase.getKnowledgeBaseDescription());
219 updateParam.put("avatar", "core/dataset/commonDatasetColor");
221 return webClient.put()
222 .uri(maaSPlatform.getServerIp() + FastGptConstant.UPDATE_DATASET_URL)
223 .contentType(APPLICATION_JSON)
224 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
225 .bodyValue(updateParam)
227 .bodyToMono(CreateDataSetResponse.class)
228 .flatMap(response -> {
229 if (response.getCode() == 200) {
230 return Mono.fromRunnable(() -> {
231 knowledgeBase.setUpdateTime(TimeUtil.getNowTime());
232 datasetMapper.updateKnowledgeBase(knowledgeBase);
233 }).then(Mono.just(new ServiceResult(new ResultHeader(200, "update success"))));
235 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
238 .onErrorResume(e -> {
239 log.error("Error occurred while delete dataset: {}", e.getMessage());
240 return Mono.just(new ServiceResult(new ResultHeader(500, "update failed")));
245 public Mono<ServiceResult> uploadFiles(Flux<FilePart> fileParts, String knowledgeBaseId, String serverIp) {
246 return fileParts.flatMap(filePart -> uploadFile(filePart, knowledgeBaseId, serverIp))
247 .then(Mono.defer(() -> handleFileId(knowledgeBaseId, serverIp)))
248 .onErrorResume(e -> {
249 log.error("Error occurred during file upload: {}", e.getMessage());
250 return Mono.just(new ServiceResult(new ResultHeader(500, "file upload failed")));
255 public Mono<ServiceResult> deleteFile(String fileId, String serverIp) {
256 return webClient.delete().uri(serverIp + FastGptConstant.DELETE_FILE_URL + fileId)
257 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
259 .bodyToMono(CreateDataSetResponse.class)
260 .flatMap(response -> {
261 if (response.getCode() == 200) {
262 return Mono.fromRunnable(() -> datasetMapper.deleteFileByFileId(fileId)).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete file success"))));
264 return Mono.just(new ServiceResult(new ResultHeader(response.getCode(), response.getStatusText())));
267 .onErrorResume(e -> {
268 log.error("Error occurred while delete dataset: {}", e.getMessage());
269 return Mono.just(new ServiceResult(new ResultHeader(500, "delete file failed")));