1 package org.onap.usecaseui.llmadaptation.service.impl;
3 import com.alibaba.fastjson2.JSONArray;
4 import com.alibaba.fastjson2.JSONObject;
5 import com.fasterxml.jackson.databind.ObjectMapper;
6 import lombok.extern.slf4j.Slf4j;
7 import org.onap.usecaseui.llmadaptation.bean.Application;
8 import org.onap.usecaseui.llmadaptation.bean.KnowledgeBase;
9 import org.onap.usecaseui.llmadaptation.bean.ResultHeader;
10 import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
11 import org.onap.usecaseui.llmadaptation.bean.fastgpt.CreateDataSetResponse;
12 import org.onap.usecaseui.llmadaptation.bean.fastgpt.application.*;
13 import org.onap.usecaseui.llmadaptation.constant.FastGptConstant;
14 import org.onap.usecaseui.llmadaptation.mapper.FastGptApplicationMapper;
15 import org.onap.usecaseui.llmadaptation.mapper.FastGptDatasetMapper;
16 import org.onap.usecaseui.llmadaptation.service.FastGptApplicationService;
17 import org.onap.usecaseui.llmadaptation.util.TimeUtil;
18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.core.io.ResourceLoader;
20 import org.springframework.stereotype.Service;
21 import org.springframework.util.CollectionUtils;
22 import org.springframework.web.reactive.function.client.WebClient;
23 import reactor.core.publisher.Flux;
24 import reactor.core.publisher.Mono;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.UUID;
31 import java.util.concurrent.atomic.AtomicBoolean;
33 import static org.springframework.http.MediaType.APPLICATION_JSON;
37 public class FastGptApplicationServiceImpl implements FastGptApplicationService {
39 private ResourceLoader resourceLoader;
42 private FastGptApplicationMapper fastGptApplicationMapper;
45 private WebClient webClient;
48 private FastGptDatasetMapper fastGptDatasetMapper;
50 private final ObjectMapper objectMapper = new ObjectMapper();
52 public Mono<ServiceResult> createApplication(Application application) {
53 try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.CREATE_APP_PARAM_FILE_URL).getInputStream()) {
54 CreateApplicationParam createApplicationParam = objectMapper.readValue(inputStream, CreateApplicationParam.class);
55 createApplicationParam.setName(application.getApplicationName());
57 return createApplication(createApplicationParam, application)
59 log.error("Error occurred while creating application: {}", e.getMessage());
60 return Mono.just(new ServiceResult(new ResultHeader(500, "Application creation failed")));
63 } catch (IOException e) {
64 log.error("Error occurred while reading input file: {}", e.getMessage());
65 return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read input file")));
69 private Mono<ServiceResult> createApplication(CreateApplicationParam createApplicationParam, Application application) {
70 return webClient.post()
71 .uri(FastGptConstant.CREATE_APPLICATION)
72 .contentType(APPLICATION_JSON)
73 .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
74 .bodyValue(createApplicationParam)
76 .bodyToMono(CreateDataSetResponse.class)
77 .flatMap(response -> {
78 if (response.getCode() == 200) {
79 return handleApplicationResponse(response, application);
81 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
85 private Mono<ServiceResult> handleApplicationResponse(CreateDataSetResponse createDataSetResponse, Application application) {
86 String data = String.valueOf(createDataSetResponse.getData());
87 application.setApplicationId(data);
88 String url = FastGptConstant.UPDATE_APPLICATION + data;
89 UpdateApplicationParam updateApplicationParam = new UpdateApplicationParam();
90 updateApplicationParam.setAvatar("/imgs/app/avatar/simple.svg");
91 updateApplicationParam.setDefaultPermission(0);
92 updateApplicationParam.setName(application.getApplicationName());
93 updateApplicationParam.setIntro(application.getApplicationDescription());
95 return webClient.put()
97 .contentType(APPLICATION_JSON)
98 .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
99 .bodyValue(updateApplicationParam)
101 .bodyToMono(CreateDataSetResponse.class)
102 .flatMap(response -> {
103 if (response.getCode() == 200) {
104 return publishApplication(application, data);
106 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
110 private Mono<ServiceResult> publishApplication(Application application, String data) {
111 try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.PUBLISH_APP_PARAM_FILE_URL).getInputStream()) {
112 PublishApplicationParam publishApplicationParam = objectMapper.readValue(inputStream, PublishApplicationParam.class);
113 publishApplicationParam.setVersionName(TimeUtil.getNowTime());
114 publishApplicationParam.getChatConfig().setWelcomeText(application.getOpeningRemarks());
115 setApplicationParameters(application, publishApplicationParam);
116 String publishUrl = FastGptConstant.PUBLISH_APPLICATION + data;
118 return webClient.post()
120 .contentType(APPLICATION_JSON)
121 .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
122 .bodyValue(publishApplicationParam)
124 .bodyToMono(CreateDataSetResponse.class)
125 .flatMap(response -> {
126 if (response.getCode() == 200) {
127 fastGptApplicationMapper.insertApplication(application);
128 return Mono.just(new ServiceResult(new ResultHeader(200, "Application created successfully")));
130 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
132 } catch (IOException e) {
133 log.error("Error occurred while reading publish parameters: {}", e.getMessage());
134 return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read publish parameters")));
138 private void setApplicationParameters(Application application, PublishApplicationParam publishApplicationParam) {
139 publishApplicationParam.getNodes().forEach(node -> {
140 if ("chatNode".equals(node.getFlowNodeType())) {
141 node.getInputs().forEach(input -> {
142 switch (input.getKey()) {
144 input.setValue(application.getTemperature());
147 input.setValue(application.getPrompt());
150 log.info(application.getLargeModelName());
151 input.setValue(application.getLargeModelName());
155 } else if ("datasetSearchNode".equals(node.getFlowNodeType())) {
156 node.getInputs().forEach(input -> {
157 if ("datasets".equals(input.getKey())) {
158 JSONObject jsonObject = new JSONObject();
159 jsonObject.put("datasetId", application.getKnowledgeBaseId());
160 List<JSONObject> list = new ArrayList<>();
161 list.add(jsonObject);
162 input.setValue(list);
169 public Flux<String> chat(JSONObject question) {
170 log.info(JSONObject.toJSONString(question));
171 ChatParam chatParam = new ChatParam();
172 chatParam.setAppId(question.getString("applicationId"));
173 chatParam.setStream(true);
174 chatParam.setDetail(true);
175 chatParam.setChatId(UUID.randomUUID().toString());
176 chatParam.setResponseChatItemId(UUID.randomUUID().toString());
177 JSONObject time = new JSONObject();
178 time.put("cTime", TimeUtil.getFormattedDateTime());
179 chatParam.setVariables(time);
180 Message message = new Message();
181 message.setContent(question.getString("question"));
182 message.setDataId(UUID.randomUUID().toString());
183 message.setRole("user");
184 List<Message> messages = new ArrayList<>();
185 messages.add(message);
186 chatParam.setMessages(messages);
187 AtomicBoolean isDone = new AtomicBoolean(false);
188 return webClient.post()
189 .uri(FastGptConstant.APPLICATION_CHAT_URL)
190 .contentType(APPLICATION_JSON)
191 .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
192 .bodyValue(chatParam)
194 .bodyToFlux(String.class).flatMap(response -> parseAndTransform(response, isDone))
195 .onErrorResume(throwable -> {
196 log.error("An error occurred {}", throwable.getMessage());
197 return Flux.just("Network Error");
201 private Flux<String> parseAndTransform(String param, AtomicBoolean isDone) {
205 JSONObject jsonObject = JSONObject.parseObject(param);
206 if (!jsonObject.containsKey("choices")) {
209 JSONArray choices = jsonObject.getJSONArray("choices");
210 JSONObject choice = choices.getJSONObject(0);
211 if ("stop".equals(choice.getString("finish_reason"))) {
215 String string = choice.getJSONObject("delta").getString("content");
217 string = string.replace(" ", "__SPACE__");
218 return Flux.just(string);
221 public Mono<ServiceResult> removeApplication(String applicationId) {
222 String url = FastGptConstant.DELETE_APPLICATION + applicationId;
224 return webClient.delete()
226 .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
228 .bodyToMono(CreateDataSetResponse.class)
229 .flatMap(response -> {
230 if (response.getCode() == 200) {
231 return Mono.fromRunnable(() -> {
233 fastGptApplicationMapper.deleteApplicationById(applicationId);
234 } catch (Exception dbException) {
235 throw new RuntimeException("Database operation failed", dbException); // 抛出新异常
237 }).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete success"))));
239 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
242 .onErrorResume(e -> {
243 log.error("Error occurred while delete dataset: {}", e.getMessage());
244 return Mono.just(new ServiceResult(new ResultHeader(500, "delete failed")));
248 public ServiceResult getApplications() {
249 List<Application> allApplication = fastGptApplicationMapper.getAllApplication();
250 if (CollectionUtils.isEmpty(allApplication)) {
251 return new ServiceResult(new ResultHeader(200, "no application"), allApplication);
253 allApplication.forEach(application -> {
254 KnowledgeBase knowledgeBaseRecordById = fastGptDatasetMapper.getKnowledgeBaseRecordById(application.getKnowledgeBaseId());
255 if (knowledgeBaseRecordById != null) {
256 application.setOperatorId(knowledgeBaseRecordById.getOperatorId());
257 application.setOperatorName(knowledgeBaseRecordById.getOperatorName());
258 application.setMaaSPlatformId(knowledgeBaseRecordById.getMaaSPlatformId());
259 application.setMaaSPlatformName(knowledgeBaseRecordById.getMaaSPlatformName());
260 application.setKnowledgeBaseName(knowledgeBaseRecordById.getKnowledgeBaseName());
263 return new ServiceResult(new ResultHeader(200, "success"), allApplication);
266 public ServiceResult getApplicationById(String applicationId) {
267 Application application = fastGptApplicationMapper.getApplicationById(applicationId);
268 if (application == null) {
269 return new ServiceResult(new ResultHeader(200, "no application"), application);
271 KnowledgeBase knowledgeBaseRecordById = fastGptDatasetMapper.getKnowledgeBaseRecordById(application.getKnowledgeBaseId());
272 application.setOperatorId(knowledgeBaseRecordById.getOperatorId());
273 application.setOperatorName(knowledgeBaseRecordById.getOperatorName());
274 application.setMaaSPlatformId(knowledgeBaseRecordById.getMaaSPlatformId());
275 application.setMaaSPlatformName(knowledgeBaseRecordById.getMaaSPlatformName());
276 application.setKnowledgeBaseName(knowledgeBaseRecordById.getKnowledgeBaseName());
277 return new ServiceResult(new ResultHeader(200, "success"), application);