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.ResultHeader;
9 import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
10 import org.onap.usecaseui.llmadaptation.bean.fastgpt.dataset.CreateDataSetResponse;
11 import org.onap.usecaseui.llmadaptation.bean.fastgpt.application.*;
12 import org.onap.usecaseui.llmadaptation.constant.CommonConstant;
13 import org.onap.usecaseui.llmadaptation.constant.FastGptConstant;
14 import org.onap.usecaseui.llmadaptation.mapper.ApplicationMapper;
15 import org.onap.usecaseui.llmadaptation.service.FastGptApplicationService;
16 import org.onap.usecaseui.llmadaptation.util.TimeUtil;
17 import org.springframework.beans.factory.annotation.Autowired;
18 import org.springframework.core.io.ResourceLoader;
19 import org.springframework.stereotype.Service;
20 import org.springframework.web.reactive.function.client.WebClient;
21 import reactor.core.publisher.Flux;
22 import reactor.core.publisher.Mono;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.util.ArrayList;
27 import java.util.List;
28 import java.util.UUID;
29 import java.util.concurrent.atomic.AtomicBoolean;
31 import static org.springframework.http.MediaType.APPLICATION_JSON;
35 public class FastGptApplicationServiceImpl implements FastGptApplicationService {
37 private ResourceLoader resourceLoader;
40 private ApplicationMapper applicationMapper;
43 private WebClient webClient;
45 private final ObjectMapper objectMapper = new ObjectMapper();
48 public Mono<ServiceResult> createApplication(Application application, String serverIp) {
49 try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.CREATE_APP_PARAM_FILE_URL).getInputStream()) {
50 CreateApplicationParam createApplicationParam = objectMapper.readValue(inputStream, CreateApplicationParam.class);
51 createApplicationParam.setName(application.getApplicationName());
53 return createApplication(createApplicationParam, application, serverIp)
55 log.error("Error occurred while creating application: {}", e.getMessage());
56 return Mono.just(new ServiceResult(new ResultHeader(500, "Application creation failed")));
59 } catch (IOException e) {
60 log.error("Error occurred while reading input file: {}", e.getMessage());
61 return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read input file")));
65 private Mono<ServiceResult> createApplication(CreateApplicationParam createApplicationParam, Application application, String serverIp) {
66 return webClient.post()
67 .uri(serverIp + FastGptConstant.CREATE_APPLICATION)
68 .contentType(APPLICATION_JSON)
69 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
70 .bodyValue(createApplicationParam)
72 .bodyToMono(CreateDataSetResponse.class)
73 .flatMap(response -> {
74 if (response.getCode() == 200) {
75 return handleApplicationResponse(String.valueOf(response.getData()), application, serverIp);
77 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
81 private Mono<ServiceResult> handleApplicationResponse(String dataId, Application application, String serverIp) {
82 application.setApplicationId(dataId);
83 String url = serverIp + FastGptConstant.UPDATE_APPLICATION + dataId;
84 UpdateApplicationParam updateApplicationParam = new UpdateApplicationParam();
85 updateApplicationParam.setAvatar("/imgs/app/avatar/simple.svg");
86 updateApplicationParam.setDefaultPermission(0);
87 updateApplicationParam.setName(application.getApplicationName());
88 updateApplicationParam.setIntro(application.getApplicationDescription());
90 return webClient.put()
92 .contentType(APPLICATION_JSON)
93 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
94 .bodyValue(updateApplicationParam)
96 .bodyToMono(CreateDataSetResponse.class)
97 .flatMap(response -> {
98 if (response.getCode() == 200) {
99 return publishApplication(application, dataId, serverIp);
101 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
105 private Mono<ServiceResult> publishApplication(Application application, String data, String serverIp) {
106 try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.PUBLISH_APP_PARAM_FILE_URL).getInputStream()) {
107 PublishApplicationParam publishApplicationParam = objectMapper.readValue(inputStream, PublishApplicationParam.class);
108 publishApplicationParam.setVersionName(TimeUtil.getNowTime());
109 publishApplicationParam.getChatConfig().setWelcomeText(application.getOpeningRemarks());
110 setApplicationParameters(application, publishApplicationParam);
111 String publishUrl = serverIp + FastGptConstant.PUBLISH_APPLICATION + data;
113 return webClient.post()
115 .contentType(APPLICATION_JSON)
116 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
117 .bodyValue(publishApplicationParam)
119 .bodyToMono(CreateDataSetResponse.class)
120 .flatMap(response -> {
121 if (response.getCode() == 200) {
122 applicationMapper.insertApplication(application);
123 return Mono.just(new ServiceResult(new ResultHeader(200, "Application created successfully")));
125 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
127 } catch (IOException e) {
128 log.error("Error occurred while reading publish parameters: {}", e.getMessage());
129 return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read publish parameters")));
133 private void setApplicationParameters(Application application, PublishApplicationParam publishApplicationParam) {
134 publishApplicationParam.getNodes().forEach(node -> {
135 if ("chatNode".equals(node.getFlowNodeType())) {
136 node.getInputs().forEach(input -> {
137 switch (input.getKey()) {
139 input.setValue(application.getTemperature());
142 input.setValue(application.getPrompt());
145 log.info(application.getLargeModelName());
146 input.setValue(application.getLargeModelName());
150 } else if ("datasetSearchNode".equals(node.getFlowNodeType())) {
151 node.getInputs().forEach(input -> {
152 if ("datasets".equals(input.getKey())) {
153 JSONObject jsonObject = new JSONObject();
154 jsonObject.put("datasetId", application.getKnowledgeBaseId());
155 List<JSONObject> list = new ArrayList<>();
156 list.add(jsonObject);
157 input.setValue(list);
165 public Flux<String> chat(JSONObject question, String serverIp) {
166 ChatParam chatParam = new ChatParam();
167 chatParam.setAppId(question.getString("applicationId"));
168 chatParam.setStream(true);
169 chatParam.setDetail(true);
170 chatParam.setChatId(UUID.randomUUID().toString());
171 chatParam.setResponseChatItemId(UUID.randomUUID().toString());
172 JSONObject time = new JSONObject();
173 time.put("cTime", TimeUtil.getFormattedDateTime());
174 chatParam.setVariables(time);
175 Message message = new Message();
176 message.setContent(question.getString("question"));
177 message.setDataId(UUID.randomUUID().toString());
178 message.setRole("user");
179 List<Message> messages = new ArrayList<>();
180 messages.add(message);
181 chatParam.setMessages(messages);
182 AtomicBoolean isDone = new AtomicBoolean(false);
183 return webClient.post()
184 .uri(serverIp + FastGptConstant.APPLICATION_CHAT_URL)
185 .contentType(APPLICATION_JSON)
186 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
187 .bodyValue(chatParam)
189 .bodyToFlux(String.class).flatMap(response -> parseAndTransform(response, isDone))
190 .onErrorResume(throwable -> {
191 log.error("An error occurred {}", throwable.getMessage());
192 return Flux.just("Network Error");
196 private Flux<String> parseAndTransform(String param, AtomicBoolean isDone) {
200 JSONObject jsonObject = JSONObject.parseObject(param);
201 if (!jsonObject.containsKey("choices")) {
204 JSONArray choices = jsonObject.getJSONArray("choices");
205 JSONObject choice = choices.getJSONObject(0);
206 if ("stop".equals(choice.getString("finish_reason"))) {
208 return Flux.just("[DONE]");
210 String string = choice.getJSONObject("delta").getString("content");
212 string = string.replace(" ", "__SPACE__");
213 return Flux.just(string);
217 public Mono<ServiceResult> removeApplication(String applicationId, String serverIp) {
218 String url = serverIp + FastGptConstant.DELETE_APPLICATION + applicationId;
219 return webClient.delete()
221 .header(CommonConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
223 .bodyToMono(CreateDataSetResponse.class)
224 .flatMap(response -> {
225 if (response.getCode() == 200) {
226 return Mono.fromRunnable(() -> {
228 applicationMapper.deleteApplicationById(applicationId);
229 } catch (Exception dbException) {
230 throw new RuntimeException("Database operation failed", dbException);
232 }).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete success"))));
234 return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
237 .onErrorResume(e -> {
238 log.error("Error occurred while delete dataset: {}", e.getMessage());
239 return Mono.just(new ServiceResult(new ResultHeader(500, "delete failed")));
244 public Mono<ServiceResult> editApplication(Application application, String serverIp) {
245 return handleApplicationResponse(application.getApplicationId(), application, serverIp);