Add knowledge base and application 93/139593/2
authorkaixiliu <liukaixi@chinamobile.com>
Wed, 27 Nov 2024 10:02:27 +0000 (18:02 +0800)
committerKaixi LIU <liukaixi@chinamobile.com>
Tue, 3 Dec 2024 07:01:08 +0000 (07:01 +0000)
Issue-ID: USECASEUI-844
Change-Id: I483a3d473ad96357fa5e36bc520ad69a25b9f66b
Signed-off-by: kaixiliu <liukaixi@chinamobile.com>
14 files changed:
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/constant/FastGptConstant.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/ApplicationController.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/DatasetController.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptApplicationMapper.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptDatasetMapper.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptApplicationService.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptDatasetService.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptApplicationServiceImpl.java [new file with mode: 0644]
llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptDatasetServiceImpl.java [new file with mode: 0644]
llm-adaptation/src/main/resources/Param/createApplication.json [new file with mode: 0644]
llm-adaptation/src/main/resources/Param/publishApplication.json [new file with mode: 0644]
llm-adaptation/src/main/resources/llm-adaptation-init.sql
llm-adaptation/src/main/resources/mapper/FastGptApplicationMapper.xml [new file with mode: 0644]
llm-adaptation/src/main/resources/mapper/FastGptDatasetMapper.xml [new file with mode: 0644]

diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/constant/FastGptConstant.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/constant/FastGptConstant.java
new file mode 100644 (file)
index 0000000..7aefa8f
--- /dev/null
@@ -0,0 +1,29 @@
+package org.onap.usecaseui.llmadaptation.constant;
+
+public class FastGptConstant {
+    public static final String COOKIE = "Cookie";
+
+    public static final String COOKIE_VALUE = "fastgpt_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NzFmNTQ2MGM4Zjc3YTFjMGYzZTUyYmEiLCJ0ZWFtSWQiOiI2NzFmNTQ2MGM4Zjc3YTFjMGYzZTUyYzAiLCJ0bWJJZCI6IjY3MWY1NDYwYzhmNzdhMWMwZjNlNTJjMiIsImlzUm9vdCI6dHJ1ZSwiZXhwIjoxNzMzMjc0Mzc2LCJpYXQiOjE3MzI2Njk1NzZ9.NdJ_ShISQOa1f5AvGsfq8Zrh4g4e2JwtX1TZ2iCLN6I";
+
+    public static final String CREATE_DATASET_URL = "http://172.22.16.126:3000/api/core/dataset/create";
+
+    public static final String UPLOAD_FILE_URL = "http://172.22.16.126:3000/api/common/file/upload";
+
+    public static final String CRATE_COLLECTION_URL = "http://172.22.16.126:3000/api/core/dataset/collection/create/fileId";
+
+    public static final String DELETE_DATASET_URL = "http://172.22.16.126:3000/api/core/dataset/delete?id=";
+
+    public static final String CREATE_APPLICATION = "http://172.22.16.126:3000/api/core/app/create";
+
+    public static final String UPDATE_APPLICATION = "http://172.22.16.126:3000/api/core/app/update?appId=";
+
+    public static final String PUBLISH_APPLICATION = "http://172.22.16.126:3000/api/core/app/version/publish?appId=";
+
+    public static final String CREATE_APP_PARAM_FILE_URL = "classpath:Param/createApplication.json";
+
+    public static final String PUBLISH_APP_PARAM_FILE_URL = "classpath:Param/publishApplication.json";
+
+    public static final String APPLICATION_CHAT_URL = "http://172.22.16.126:3000/api/v1/chat/completions";
+
+    public static final String DELETE_APPLICATION = "http://172.22.16.126:3000/api/core/app/del?appId=";
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/ApplicationController.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/ApplicationController.java
new file mode 100644 (file)
index 0000000..f10495e
--- /dev/null
@@ -0,0 +1,46 @@
+package org.onap.usecaseui.llmadaptation.controller;
+
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.usecaseui.llmadaptation.bean.Application;
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import org.onap.usecaseui.llmadaptation.service.FastGptApplicationService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/usecaseui-llm-adaptation/v1/application")
+public class ApplicationController {
+
+    @Autowired
+    private FastGptApplicationService fastGptApplicationService;
+
+    @PostMapping(value = "/create", produces = MediaType.APPLICATION_JSON_VALUE)
+    public Mono<ServiceResult> createApplication(@RequestBody Application application) {
+        return fastGptApplicationService.createApplication(application);
+    }
+
+    @DeleteMapping(value = "/delete/{applicationId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public Mono<ServiceResult> removeKnowledgeBase(@PathVariable("applicationId") String applicationId) {
+        return fastGptApplicationService.removeApplication(applicationId);
+    }
+
+    @PostMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
+    public Flux<String> streamData(@RequestBody JSONObject question) {
+        return fastGptApplicationService.chat(question);
+    }
+
+    @GetMapping(value = {"/query"}, produces = MediaType.APPLICATION_JSON_VALUE)
+    public ServiceResult getApplications() {
+        return fastGptApplicationService.getApplications();
+    }
+
+    @GetMapping(value = {"/queryById/{applicationId}"}, produces = MediaType.APPLICATION_JSON_VALUE)
+    public ServiceResult getApplications(@PathVariable("applicationId") String applicationId) {
+        return fastGptApplicationService.getApplicationById(applicationId);
+    }
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/DatasetController.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/controller/DatasetController.java
new file mode 100644 (file)
index 0000000..5425cd6
--- /dev/null
@@ -0,0 +1,54 @@
+package org.onap.usecaseui.llmadaptation.controller;
+
+import lombok.extern.slf4j.Slf4j;
+import org.onap.usecaseui.llmadaptation.bean.KnowledgeBase;
+import org.onap.usecaseui.llmadaptation.bean.ResultHeader;
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import org.onap.usecaseui.llmadaptation.mapper.FastGptDatasetMapper;
+import org.onap.usecaseui.llmadaptation.service.FastGptDatasetService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.http.codec.multipart.FilePart;
+import org.springframework.web.bind.annotation.*;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+@Slf4j
+@RestController
+@RequestMapping("/api/usecaseui-llm-adaptation/v1/knowledgeBase")
+public class DatasetController {
+    @Autowired
+    private FastGptDatasetService fastGptDatasetService;
+
+    @Autowired
+    private FastGptDatasetMapper fastGptDatasetMapper;
+
+    @PostMapping(value = "/create", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
+    public Mono<ServiceResult> handleFileUpload(@RequestPart("files") Flux<FilePart> fileParts,
+                                                @RequestPart("metaData") String metaData) {
+        return fastGptDatasetService.createDataset(fileParts, metaData);
+    }
+
+    @DeleteMapping(value = "/delete/{knowledgeBaseId}", produces = MediaType.APPLICATION_JSON_VALUE)
+    public Mono<ServiceResult> removeKnowledgeBase(@PathVariable("knowledgeBaseId") String knowledgeBaseId) {
+        return fastGptDatasetService.removeDataset(knowledgeBaseId);
+    }
+
+    @GetMapping(value = {"/query"}, produces = MediaType.APPLICATION_JSON_VALUE)
+    public ServiceResult getKnowledgeBaseRecord() {
+        return fastGptDatasetService.getDataSetRecord();
+    }
+
+    @GetMapping(value = {"/queryById/{knowledgeBaseId}"}, produces = MediaType.APPLICATION_JSON_VALUE)
+    public ServiceResult getKnowledgeBaseRecordById(@PathVariable("knowledgeBaseId") String knowledgeBaseId) {
+        return fastGptDatasetService.geDatasetById(knowledgeBaseId);
+    }
+
+    @GetMapping(value = {"/queryByMaaSId/{maaSPlatformId}"}, produces = MediaType.APPLICATION_JSON_VALUE)
+    public ServiceResult getKnowledgeBaseRecordByMaaSId(@PathVariable("maaSPlatformId") String maaSPlatformId) {
+        List<KnowledgeBase> knowledgeBaseByMaaSId = fastGptDatasetMapper.getKnowledgeBaseByMaaSId(maaSPlatformId);
+        return new ServiceResult(new ResultHeader(200, "success"), knowledgeBaseByMaaSId);
+    }
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptApplicationMapper.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptApplicationMapper.java
new file mode 100644 (file)
index 0000000..f3b6506
--- /dev/null
@@ -0,0 +1,18 @@
+package org.onap.usecaseui.llmadaptation.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.onap.usecaseui.llmadaptation.bean.Application;
+
+import java.util.List;
+
+@Mapper
+public interface FastGptApplicationMapper {
+    List<Application> getAllApplication();
+
+    int insertApplication(@Param(value = "application") Application application);
+
+    int deleteApplicationById(@Param(value = "applicationId") String applicationId);
+
+    Application getApplicationById(@Param(value = "applicationId") String applicationId);
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptDatasetMapper.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/mapper/FastGptDatasetMapper.java
new file mode 100644 (file)
index 0000000..4114f1a
--- /dev/null
@@ -0,0 +1,26 @@
+package org.onap.usecaseui.llmadaptation.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.onap.usecaseui.llmadaptation.bean.KnowledgeBase;
+
+import java.util.List;
+
+@Mapper
+public interface FastGptDatasetMapper {
+    int insertKnowledgeBaseRecord(@Param(value = "knowledgeBase") KnowledgeBase knowledgeBase);
+
+    int insertFileName(@Param(value = "fileId") String fileId,@Param(value = "fileName") String fileName,@Param(value = "knowledgeBaseId") String knowledgeBaseId);
+
+    List<KnowledgeBase> getKnowledgeBaseRecords();
+
+    List<String> getFileNamesByKnowledgeBaseId(@Param(value = "knowledgeBaseId") String knowledgeBaseId);
+
+    KnowledgeBase getKnowledgeBaseRecordById(@Param(value = "knowledgeBaseId") String knowledgeBaseId);
+
+    int deleteKnowledgeBaseByUuid(@Param(value = "knowledgeBaseId") String knowledgeBaseId);
+
+    List<KnowledgeBase> getKnowledgeBaseByMaaSId(@Param(value = "maaSPlatformId") String maaSPlatformId);
+
+    int deleteFileById(@Param(value = "knowledgeBaseId") String knowledgeBaseId);
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptApplicationService.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptApplicationService.java
new file mode 100644 (file)
index 0000000..19e6c11
--- /dev/null
@@ -0,0 +1,19 @@
+package org.onap.usecaseui.llmadaptation.service;
+
+import com.alibaba.fastjson2.JSONObject;
+import org.onap.usecaseui.llmadaptation.bean.Application;
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public interface FastGptApplicationService {
+    Mono<ServiceResult> createApplication(Application application);
+
+    Flux<String> chat(JSONObject question);
+
+    Mono<ServiceResult> removeApplication(String applicationId);
+
+    ServiceResult getApplications();
+
+    ServiceResult getApplicationById(String applicationId);
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptDatasetService.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/FastGptDatasetService.java
new file mode 100644 (file)
index 0000000..901b1e0
--- /dev/null
@@ -0,0 +1,16 @@
+package org.onap.usecaseui.llmadaptation.service;
+
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import org.springframework.http.codec.multipart.FilePart;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+public interface FastGptDatasetService {
+    Mono<ServiceResult> createDataset(Flux<FilePart> fileParts, String metaData);
+
+    Mono<ServiceResult> removeDataset(String knowledgeBaseId);
+
+    ServiceResult getDataSetRecord();
+
+    ServiceResult geDatasetById(String knowledgeBaseId);
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptApplicationServiceImpl.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptApplicationServiceImpl.java
new file mode 100644 (file)
index 0000000..d8f68ad
--- /dev/null
@@ -0,0 +1,279 @@
+package org.onap.usecaseui.llmadaptation.service.impl;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.onap.usecaseui.llmadaptation.bean.Application;
+import org.onap.usecaseui.llmadaptation.bean.KnowledgeBase;
+import org.onap.usecaseui.llmadaptation.bean.ResultHeader;
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import org.onap.usecaseui.llmadaptation.bean.fastgpt.CreateDataSetResponse;
+import org.onap.usecaseui.llmadaptation.bean.fastgpt.application.*;
+import org.onap.usecaseui.llmadaptation.constant.FastGptConstant;
+import org.onap.usecaseui.llmadaptation.mapper.FastGptApplicationMapper;
+import org.onap.usecaseui.llmadaptation.mapper.FastGptDatasetMapper;
+import org.onap.usecaseui.llmadaptation.service.FastGptApplicationService;
+import org.onap.usecaseui.llmadaptation.util.TimeUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+
+@Slf4j
+@Service
+public class FastGptApplicationServiceImpl implements FastGptApplicationService {
+    @Autowired
+    private ResourceLoader resourceLoader;
+
+    @Autowired
+    private FastGptApplicationMapper fastGptApplicationMapper;
+
+    @Autowired
+    private WebClient webClient;
+
+    @Autowired
+    private FastGptDatasetMapper fastGptDatasetMapper;
+
+    private final ObjectMapper objectMapper = new ObjectMapper();
+
+    public Mono<ServiceResult> createApplication(Application application) {
+        try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.CREATE_APP_PARAM_FILE_URL).getInputStream()) {
+            CreateApplicationParam createApplicationParam = objectMapper.readValue(inputStream, CreateApplicationParam.class);
+            createApplicationParam.setName(application.getApplicationName());
+
+            return createApplication(createApplicationParam, application)
+                    .onErrorResume(e -> {
+                        log.error("Error occurred while creating application: {}", e.getMessage());
+                        return Mono.just(new ServiceResult(new ResultHeader(500, "Application creation failed")));
+                    });
+
+        } catch (IOException e) {
+            log.error("Error occurred while reading input file: {}", e.getMessage());
+            return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read input file")));
+        }
+    }
+
+    private Mono<ServiceResult> createApplication(CreateApplicationParam createApplicationParam, Application application) {
+        return webClient.post()
+                .uri(FastGptConstant.CREATE_APPLICATION)
+                .contentType(APPLICATION_JSON)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .bodyValue(createApplicationParam)
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() == 200) {
+                        return handleApplicationResponse(response, application);
+                    }
+                    return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
+                });
+    }
+
+    private Mono<ServiceResult> handleApplicationResponse(CreateDataSetResponse createDataSetResponse, Application application) {
+        String data = String.valueOf(createDataSetResponse.getData());
+        application.setApplicationId(data);
+        String url = FastGptConstant.UPDATE_APPLICATION + data;
+        UpdateApplicationParam updateApplicationParam = new UpdateApplicationParam();
+        updateApplicationParam.setAvatar("/imgs/app/avatar/simple.svg");
+        updateApplicationParam.setDefaultPermission(0);
+        updateApplicationParam.setName(application.getApplicationName());
+        updateApplicationParam.setIntro(application.getApplicationDescription());
+
+        return webClient.put()
+                .uri(url)
+                .contentType(APPLICATION_JSON)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .bodyValue(updateApplicationParam)
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() == 200) {
+                        return publishApplication(application, data);
+                    }
+                    return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
+                });
+    }
+
+    private Mono<ServiceResult> publishApplication(Application application, String data) {
+        try (InputStream inputStream = resourceLoader.getResource(FastGptConstant.PUBLISH_APP_PARAM_FILE_URL).getInputStream()) {
+            PublishApplicationParam publishApplicationParam = objectMapper.readValue(inputStream, PublishApplicationParam.class);
+            publishApplicationParam.setVersionName(TimeUtil.getNowTime());
+            publishApplicationParam.getChatConfig().setWelcomeText(application.getOpeningRemarks());
+            setApplicationParameters(application, publishApplicationParam);
+            String publishUrl = FastGptConstant.PUBLISH_APPLICATION + data;
+
+            return webClient.post()
+                    .uri(publishUrl)
+                    .contentType(APPLICATION_JSON)
+                    .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                    .bodyValue(publishApplicationParam)
+                    .retrieve()
+                    .bodyToMono(CreateDataSetResponse.class)
+                    .flatMap(response -> {
+                        if (response.getCode() == 200) {
+                            fastGptApplicationMapper.insertApplication(application);
+                            return Mono.just(new ServiceResult(new ResultHeader(200, "Application created successfully")));
+                        }
+                        return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
+                    });
+        } catch (IOException e) {
+            log.error("Error occurred while reading publish parameters: {}", e.getMessage());
+            return Mono.just(new ServiceResult(new ResultHeader(500, "Failed to read publish parameters")));
+        }
+    }
+
+    private void setApplicationParameters(Application application, PublishApplicationParam publishApplicationParam) {
+        publishApplicationParam.getNodes().forEach(node -> {
+            if ("chatNode".equals(node.getFlowNodeType())) {
+                node.getInputs().forEach(input -> {
+                    switch (input.getKey()) {
+                        case "temperature":
+                            input.setValue(application.getTemperature());
+                            break;
+                        case "systemPrompt":
+                            input.setValue(application.getPrompt());
+                            break;
+                        case "model":
+                            log.info(application.getLargeModelName());
+                            input.setValue(application.getLargeModelName());
+                            break;
+                    }
+                });
+            } else if ("datasetSearchNode".equals(node.getFlowNodeType())) {
+                node.getInputs().forEach(input -> {
+                    if ("datasets".equals(input.getKey())) {
+                        JSONObject jsonObject = new JSONObject();
+                        jsonObject.put("datasetId", application.getKnowledgeBaseId());
+                        List<JSONObject> list = new ArrayList<>();
+                        list.add(jsonObject);
+                        input.setValue(list);
+                    }
+                });
+            }
+        });
+    }
+
+    public Flux<String> chat(JSONObject question) {
+        log.info(JSONObject.toJSONString(question));
+        ChatParam chatParam = new ChatParam();
+        chatParam.setAppId(question.getString("applicationId"));
+        chatParam.setStream(true);
+        chatParam.setDetail(true);
+        chatParam.setChatId(UUID.randomUUID().toString());
+        chatParam.setResponseChatItemId(UUID.randomUUID().toString());
+        JSONObject time = new JSONObject();
+        time.put("cTime", TimeUtil.getFormattedDateTime());
+        chatParam.setVariables(time);
+        Message message = new Message();
+        message.setContent(question.getString("question"));
+        message.setDataId(UUID.randomUUID().toString());
+        message.setRole("user");
+        List<Message> messages = new ArrayList<>();
+        messages.add(message);
+        chatParam.setMessages(messages);
+        AtomicBoolean isDone = new AtomicBoolean(false);
+        return webClient.post()
+                .uri(FastGptConstant.APPLICATION_CHAT_URL)
+                .contentType(APPLICATION_JSON)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .bodyValue(chatParam)
+                .retrieve()
+                .bodyToFlux(String.class).flatMap(response -> parseAndTransform(response, isDone))
+                .onErrorResume(throwable -> {
+                    log.error("An error occurred {}", throwable.getMessage());
+                    return Flux.just("Network Error");
+                });
+    }
+
+    private Flux<String> parseAndTransform(String param, AtomicBoolean isDone) {
+        if (isDone.get()) {
+            return Flux.empty();
+        }
+        JSONObject jsonObject = JSONObject.parseObject(param);
+        if (!jsonObject.containsKey("choices")) {
+            return Flux.empty();
+        }
+        JSONArray choices = jsonObject.getJSONArray("choices");
+        JSONObject choice = choices.getJSONObject(0);
+        if ("stop".equals(choice.getString("finish_reason"))) {
+            isDone.set(true);
+            return Flux.empty();
+        }
+        String string = choice.getJSONObject("delta").getString("content");
+        isDone.set(false);
+        string = string.replace(" ", "__SPACE__");
+        return Flux.just(string);
+    }
+
+    public Mono<ServiceResult> removeApplication(String applicationId) {
+        String url = FastGptConstant.DELETE_APPLICATION + applicationId;
+
+        return webClient.delete()
+                .uri(url)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() == 200) {
+                        return Mono.fromRunnable(() -> {
+                            try {
+                                fastGptApplicationMapper.deleteApplicationById(applicationId);
+                            } catch (Exception dbException) {
+                                throw new RuntimeException("Database operation failed", dbException); // æŠ›å‡ºæ–°å¼‚常
+                            }
+                        }).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete success"))));
+                    } else {
+                        return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
+                    }
+                })
+                .onErrorResume(e -> {
+                    log.error("Error occurred while delete dataset: {}", e.getMessage());
+                    return Mono.just(new ServiceResult(new ResultHeader(500, "delete failed")));
+                });
+    }
+
+    public ServiceResult getApplications() {
+        List<Application> allApplication = fastGptApplicationMapper.getAllApplication();
+        if (CollectionUtils.isEmpty(allApplication)) {
+            return new ServiceResult(new ResultHeader(200, "no application"), allApplication);
+        }
+        allApplication.forEach(application -> {
+            KnowledgeBase knowledgeBaseRecordById = fastGptDatasetMapper.getKnowledgeBaseRecordById(application.getKnowledgeBaseId());
+            if (knowledgeBaseRecordById != null) {
+                application.setOperatorId(knowledgeBaseRecordById.getOperatorId());
+                application.setOperatorName(knowledgeBaseRecordById.getOperatorName());
+                application.setMaaSPlatformId(knowledgeBaseRecordById.getMaaSPlatformId());
+                application.setMaaSPlatformName(knowledgeBaseRecordById.getMaaSPlatformName());
+                application.setKnowledgeBaseName(knowledgeBaseRecordById.getKnowledgeBaseName());
+            }
+        });
+        return new ServiceResult(new ResultHeader(200, "success"), allApplication);
+    }
+
+    public ServiceResult getApplicationById(String applicationId) {
+        Application application = fastGptApplicationMapper.getApplicationById(applicationId);
+        if (application == null) {
+            return new ServiceResult(new ResultHeader(200, "no application"), application);
+        }
+        KnowledgeBase knowledgeBaseRecordById = fastGptDatasetMapper.getKnowledgeBaseRecordById(application.getKnowledgeBaseId());
+        application.setOperatorId(knowledgeBaseRecordById.getOperatorId());
+        application.setOperatorName(knowledgeBaseRecordById.getOperatorName());
+        application.setMaaSPlatformId(knowledgeBaseRecordById.getMaaSPlatformId());
+        application.setMaaSPlatformName(knowledgeBaseRecordById.getMaaSPlatformName());
+        application.setKnowledgeBaseName(knowledgeBaseRecordById.getKnowledgeBaseName());
+        return new ServiceResult(new ResultHeader(200, "success"), application);
+    }
+}
diff --git a/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptDatasetServiceImpl.java b/llm-adaptation/src/main/java/org/onap/usecaseui/llmadaptation/service/impl/FastGptDatasetServiceImpl.java
new file mode 100644 (file)
index 0000000..0cc1528
--- /dev/null
@@ -0,0 +1,198 @@
+package org.onap.usecaseui.llmadaptation.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.onap.usecaseui.llmadaptation.bean.KnowledgeBase;
+import org.onap.usecaseui.llmadaptation.bean.ResultHeader;
+import org.onap.usecaseui.llmadaptation.bean.ServiceResult;
+import org.onap.usecaseui.llmadaptation.bean.fastgpt.CreateCollectionParam;
+import org.onap.usecaseui.llmadaptation.bean.fastgpt.CreateDataSetParam;
+import org.onap.usecaseui.llmadaptation.bean.fastgpt.CreateDataSetResponse;
+import org.onap.usecaseui.llmadaptation.constant.FastGptConstant;
+import org.onap.usecaseui.llmadaptation.mapper.FastGptDatasetMapper;
+import org.onap.usecaseui.llmadaptation.service.FastGptDatasetService;
+import org.onap.usecaseui.llmadaptation.util.TimeUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.ContentDisposition;
+import org.springframework.http.MediaType;
+import org.springframework.http.client.MultipartBodyBuilder;
+import org.springframework.http.codec.multipart.FilePart;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import org.springframework.web.reactive.function.BodyInserters;
+import org.springframework.web.reactive.function.client.WebClient;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+import static org.springframework.http.MediaType.APPLICATION_JSON;
+
+@Slf4j
+@Service
+public class FastGptDatasetServiceImpl implements FastGptDatasetService {
+    @Autowired
+    private FastGptDatasetMapper fastGptDatasetMapper;
+
+    @Autowired
+    private WebClient webClient;
+
+    public Mono<ServiceResult> createDataset(Flux<FilePart> fileParts, String metaData) {
+        KnowledgeBase knowledgeBase = JSONObject.parseObject(metaData, KnowledgeBase.class);
+        knowledgeBase.setUpdateTime(TimeUtil.getNowTime());
+        CreateDataSetParam dataSetParam = new CreateDataSetParam();
+        dataSetParam.setAgentModel("qwen2:7b");
+        dataSetParam.setType("dataset");
+        dataSetParam.setAvatar("core/dataset/commonDatasetColor");
+        dataSetParam.setVectorModel("m3e");
+        dataSetParam.setIntro(knowledgeBase.getKnowledgeBaseDescription());
+        dataSetParam.setName(knowledgeBase.getKnowledgeBaseName());
+        return webClient.post()
+                .uri(FastGptConstant.CREATE_DATASET_URL)
+                .contentType(APPLICATION_JSON)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .bodyValue(dataSetParam)
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() == 200) {
+                        String knowledgeBaseId = String.valueOf(response.getData());
+                        return fileParts.flatMap(filePart -> uploadFile(filePart, knowledgeBaseId))
+                                .then(Mono.defer(() -> {
+                                    knowledgeBase.setKnowledgeBaseId(knowledgeBaseId);
+                                    fastGptDatasetMapper.insertKnowledgeBaseRecord(knowledgeBase);
+                                    return Mono.just(new ServiceResult(new ResultHeader(200, "create success")));
+                                }))
+                                .onErrorResume(e -> {
+                                    log.error("Error occurred during file upload: {}", e.getMessage());
+                                    return Mono.just(new ServiceResult(new ResultHeader(500, "file upload failed")));
+                                });
+                    } else {
+                        return Mono.just(new ServiceResult(new ResultHeader(500, response.getMessage())));
+                    }
+                })
+                .onErrorResume(e -> {
+                    log.error("Error occurred while creating dataset: {}", e.getMessage());
+                    return Mono.just(new ServiceResult(new ResultHeader(500, "create failed")));
+                });
+    }
+
+    private Mono<Void> uploadFile(FilePart filePart, String knowledgeBaseId) {
+        String filename = filePart.filename();
+        Flux<DataBuffer> content = filePart.content();
+
+        MultipartBodyBuilder builder = new MultipartBodyBuilder();
+        builder.part("metadata", "", APPLICATION_JSON);
+        builder.part("bucketName", "dataset");
+        builder.asyncPart("file", content, DataBuffer.class)
+                .headers(headers -> {
+                    ContentDisposition contentDisposition = ContentDisposition
+                            .builder("form-data")
+                            .name("file")
+                            .filename(filename)
+                            .build();
+                    headers.setContentDisposition(contentDisposition);
+                    headers.setContentType(MediaType.TEXT_PLAIN);
+                });
+
+        return webClient.post()
+                .uri(FastGptConstant.UPLOAD_FILE_URL)
+                .contentType(MediaType.MULTIPART_FORM_DATA)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .body(BodyInserters.fromMultipartData(builder.build()))
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() != 200) {
+                        log.error("response is {}", response);
+                        return Mono.empty();
+                    }
+                    Object data = response.getData();
+                    JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(data));
+                    String fileId = jsonObject.getString("fileId");
+                    CreateCollectionParam createCollectionParam = getCreateCollectionParam(knowledgeBaseId, fileId);
+
+                    return webClient.post()
+                            .uri(FastGptConstant.CRATE_COLLECTION_URL)
+                            .contentType(APPLICATION_JSON)
+                            .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                            .bodyValue(createCollectionParam)
+                            .retrieve()
+                            .bodyToMono(CreateDataSetResponse.class)
+                            .flatMap(responseData -> {
+                                if (responseData.getCode() == 200) {
+                                    fastGptDatasetMapper.insertFileName(fileId, filename, knowledgeBaseId);
+                                }
+                                return Mono.empty();
+                            });
+                });
+    }
+
+    @NotNull
+    private static CreateCollectionParam getCreateCollectionParam(String knowledgeBaseId, String fileId) {
+        CreateCollectionParam createCollectionParam = new CreateCollectionParam();
+        createCollectionParam.setTrainingType("chunk");
+        createCollectionParam.setDatasetId(knowledgeBaseId);
+        createCollectionParam.setChunkSize(700);
+        createCollectionParam.setChunkSplitter("");
+        createCollectionParam.setFileId(fileId);
+        createCollectionParam.setName("");
+        createCollectionParam.setQaPrompt("");
+        return createCollectionParam;
+    }
+
+    public Mono<ServiceResult> removeDataset(String knowledgeBaseId) {
+        String url = FastGptConstant.DELETE_DATASET_URL + knowledgeBaseId;
+        return webClient.delete()
+                .uri(url)
+                .header(FastGptConstant.COOKIE, FastGptConstant.COOKIE_VALUE)
+                .retrieve()
+                .bodyToMono(CreateDataSetResponse.class)
+                .flatMap(response -> {
+                    if (response.getCode() == 200) {
+                        return Mono.fromRunnable(() -> {
+                            try {
+                                fastGptDatasetMapper.deleteKnowledgeBaseByUuid(knowledgeBaseId);
+                                fastGptDatasetMapper.deleteFileById(knowledgeBaseId);
+                            } catch (Exception dbException) {
+                                throw new RuntimeException("Database operation failed", dbException); // æŠ›å‡ºæ–°å¼‚常
+                            }
+                        }).then(Mono.just(new ServiceResult(new ResultHeader(200, "delete success"))));
+                    } else {
+                        return Mono.just(new ServiceResult(new ResultHeader(500, response.getStatusText())));
+                    }
+                })
+                .onErrorResume(e -> {
+                    log.error("Error occurred while delete dataset: {}", e.getMessage());
+                    return Mono.just(new ServiceResult(new ResultHeader(500, "delete failed")));
+                });
+    }
+
+    public ServiceResult getDataSetRecord() {
+        List<KnowledgeBase> knowledgeBaseRecords = fastGptDatasetMapper.getKnowledgeBaseRecords();
+        if (CollectionUtils.isEmpty(knowledgeBaseRecords)) {
+            return new ServiceResult(new ResultHeader(200, "get datasets failed"), knowledgeBaseRecords);
+        }
+
+        knowledgeBaseRecords.forEach(knowledgeBase -> {
+            List<String> fileNamesByKnowledgeBaseId = fastGptDatasetMapper.getFileNamesByKnowledgeBaseId(knowledgeBase.getKnowledgeBaseId());
+            knowledgeBase.setFilesName(fileNamesByKnowledgeBaseId);
+        });
+        return new ServiceResult(new ResultHeader(200, "success"), knowledgeBaseRecords);
+    }
+
+    public ServiceResult geDatasetById(String knowledgeBaseId) {
+        KnowledgeBase knowledgeBase = fastGptDatasetMapper.getKnowledgeBaseRecordById(knowledgeBaseId);
+        if (knowledgeBase == null) {
+            return new ServiceResult(new ResultHeader(200, "get dataset failed"));
+        }
+        List<String> fileNamesByKnowledgeBaseId = fastGptDatasetMapper.getFileNamesByKnowledgeBaseId(knowledgeBase.getKnowledgeBaseId());
+        knowledgeBase.setFilesName(fileNamesByKnowledgeBaseId);
+
+        return new ServiceResult(new ResultHeader(200, "success"), knowledgeBase);
+    }
+
+}
diff --git a/llm-adaptation/src/main/resources/Param/createApplication.json b/llm-adaptation/src/main/resources/Param/createApplication.json
new file mode 100644 (file)
index 0000000..06edf5a
--- /dev/null
@@ -0,0 +1,400 @@
+{
+  "parentId":null,
+  "avatar":"/imgs/app/avatar/simple.svg",
+  "name":"tourism",
+  "type":"simple",
+  "modules":[
+    {
+      "nodeId":"userGuide",
+      "name":"system configuration",
+      "intro":"Can configure system parameters for applications",
+      "avatar":"core/workflow/template/systemConfig",
+      "flowNodeType":"userGuide",
+      "position":{
+        "x":531.2422736065552,
+        "y":-486.7611729549753
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"welcomeText",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "label":"core.app.Welcome Text",
+          "value":"Hello, I am Knowledge Base Assistant. Please don't forget to select the knowledge base. [Who are you] [How to use]"
+        },
+        {
+          "key":"variables",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.any",
+          "label":"core.app.Chat Variable",
+          "value":[
+
+          ]
+        },
+        {
+          "key":"questionGuide",
+          "valueType":"WorkflowIOValueTypeEnum.boolean",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"core.app.Question Guide",
+          "value":false
+        },
+        {
+          "key":"tts",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.any",
+          "label":"",
+          "value":{
+            "type":"web"
+          }
+        },
+        {
+          "key":"whisper",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.any",
+          "label":"",
+          "value":{
+            "open":false,
+            "autoSend":false,
+            "autoTTSResponse":false
+          }
+        },
+        {
+          "key":"scheduleTrigger",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.any",
+          "label":"",
+          "value":null
+        }
+      ],
+      "outputs":[
+
+      ]
+    },
+    {
+      "nodeId":"workflowStartNodeId",
+      "name":"Process begins",
+      "intro":"",
+      "avatar":"core/workflow/template/workflowStart",
+      "flowNodeType":"workflowStart",
+      "position":{
+        "x":558.4082376415505,
+        "y":123.72387429194112
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.reference",
+            "FlowNodeInputTypeEnum.textarea"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "label":"user problem",
+          "required":true,
+          "toolDescription":"user problem"
+        }
+      ],
+      "outputs":[
+        {
+          "id":"userChatInput",
+          "key":"userChatInput",
+          "label":"core.module.input.label.user question",
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "type":"FlowNodeOutputTypeEnum.static"
+        }
+      ]
+    },
+    {
+      "nodeId":"7BdojPlukIQw",
+      "name":"AI dialogue",
+      "intro":"AI Large Model Dialogue",
+      "avatar":"core/workflow/template/aiChat",
+      "flowNodeType":"chatNode",
+      "showStatus":true,
+      "position":{
+        "x":1638.509551404687,
+        "y":-341.0428450861567
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"model",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.settingLLMModel",
+            "FlowNodeInputTypeEnum.reference"
+          ],
+          "label":"core.module.input.label.aiModel",
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "value":"gpt-4o-mini"
+        },
+        {
+          "key":"temperature",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "value":3,
+          "valueType":"WorkflowIOValueTypeEnum.number",
+          "min":0,
+          "max":10,
+          "step":1
+        },
+        {
+          "key":"maxToken",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "value":1950,
+          "valueType":"WorkflowIOValueTypeEnum.number",
+          "min":100,
+          "max":4000,
+          "step":50
+        },
+        {
+          "key":"isResponseAnswerText",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "value":true,
+          "valueType":"WorkflowIOValueTypeEnum.boolean"
+        },
+        {
+          "key":"quoteTemplate",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.string"
+        },
+        {
+          "key":"quotePrompt",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.string"
+        },
+        {
+          "key":"systemPrompt",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.textarea",
+            "FlowNodeInputTypeEnum.reference"
+          ],
+          "max":3000,
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "label":"core.ai.Prompt",
+          "description":"core.app.tip.systemPromptTip",
+          "placeholder":"core.app.tip.chatNodeSystemPromptTip",
+          "value":""
+        },
+        {
+          "key":"history",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.numberInput",
+            "FlowNodeInputTypeEnum.reference"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.chatHistory",
+          "label":"core.module.input.label.chat history",
+          "required":true,
+          "min":0,
+          "max":30,
+          "value":6
+        },
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.reference",
+            "FlowNodeInputTypeEnum.textarea"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "label":"user problem",
+          "required":true,
+          "toolDescription":"user problem",
+          "value":[
+            "workflowStartNodeId",
+            "userChatInput"
+          ]
+        },
+        {
+          "key":"quoteQA",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.settingDatasetQuotePrompt"
+          ],
+          "label":"",
+          "debugLabel":"Reference to Knowledge Base",
+          "description":"",
+          "valueType":"WorkflowIOValueTypeEnum.datasetQuote",
+          "value":[
+            "iKBoX2vIzETU",
+            "quoteQA"
+          ]
+        }
+      ],
+      "outputs":[
+        {
+          "id":"history",
+          "key":"history",
+          "label":"core.module.output.label.New context",
+          "description":"core.module.output.description.New context",
+          "valueType":"WorkflowIOValueTypeEnum.chatHistory",
+          "type":"FlowNodeOutputTypeEnum.static"
+        },
+        {
+          "id":"answerText",
+          "key":"answerText",
+          "label":"core.module.output.label.Ai response content",
+          "description":"core.module.output.description.Ai response content",
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "type":"FlowNodeOutputTypeEnum.static"
+        }
+      ]
+    },
+    {
+      "nodeId":"iKBoX2vIzETU",
+      "name":"Knowledge Base Search",
+      "intro":"Call semantic retrieval and full-text retrieval capabilities to search for reference content that may be relevant to the problem from the knowledge base",
+      "avatar":"core/workflow/template/datasetSearch",
+      "flowNodeType":"datasetSearchNode",
+      "showStatus":true,
+      "position":{
+        "x":918.5901682164496,
+        "y":-227.11542247619582
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"datasets",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.selectDataset",
+            "FlowNodeInputTypeEnum.reference"
+          ],
+          "label":"core.module.input.label.Select dataset",
+          "value":[
+
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.selectDataset",
+          "list":[
+
+          ],
+          "required":true
+        },
+        {
+          "key":"similarity",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.selectDatasetParamsModal"
+          ],
+          "label":"",
+          "value":0.4,
+          "valueType":"WorkflowIOValueTypeEnum.number"
+        },
+        {
+          "key":"limit",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "value":1500,
+          "valueType":"WorkflowIOValueTypeEnum.number"
+        },
+        {
+          "key":"searchMode",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "value":"embedding"
+        },
+        {
+          "key":"usingReRank",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.boolean",
+          "value":false
+        },
+        {
+          "key":"datasetSearchUsingExtensionQuery",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.boolean",
+          "value":true
+        },
+        {
+          "key":"datasetSearchExtensionModel",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.string"
+        },
+        {
+          "key":"datasetSearchExtensionBg",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.hidden"
+          ],
+          "label":"",
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "value":""
+        },
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "FlowNodeInputTypeEnum.reference",
+            "FlowNodeInputTypeEnum.textarea"
+          ],
+          "valueType":"WorkflowIOValueTypeEnum.string",
+          "label":"user problem",
+          "required":true,
+          "toolDescription":"What needs to be retrieved",
+          "value":[
+            "workflowStartNodeId",
+            "userChatInput"
+          ]
+        }
+      ],
+      "outputs":[
+        {
+          "id":"quoteQA",
+          "key":"quoteQA",
+          "label":"core.module.Dataset quote.label",
+          "type":"FlowNodeOutputTypeEnum.static",
+          "valueType":"WorkflowIOValueTypeEnum.datasetQuote",
+          "description":"Special array format, returns an empty array when the search result is empty."
+        }
+      ]
+    }
+  ],
+  "edges":[
+    {
+      "source":"workflowStartNodeId",
+      "target":"iKBoX2vIzETU",
+      "sourceHandle":"workflowStartNodeId-source-right",
+      "targetHandle":"iKBoX2vIzETU-target-left"
+    },
+    {
+      "source":"iKBoX2vIzETU",
+      "target":"7BdojPlukIQw",
+      "sourceHandle":"iKBoX2vIzETU-source-right",
+      "targetHandle":"7BdojPlukIQw-target-left"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/llm-adaptation/src/main/resources/Param/publishApplication.json b/llm-adaptation/src/main/resources/Param/publishApplication.json
new file mode 100644 (file)
index 0000000..5f53071
--- /dev/null
@@ -0,0 +1,397 @@
+{
+  "nodes":[
+    {
+      "nodeId":"userGuide",
+      "name":"system configuration",
+      "intro":"",
+      "flowNodeType":"userGuide",
+      "position":{
+        "x":531.2422736065552,
+        "y":-486.7611729549753
+      },
+      "version":"481",
+      "inputs":[
+
+      ],
+      "outputs":[
+
+      ]
+    },
+    {
+      "nodeId":"workflowStartNodeId",
+      "name":"Process begins",
+      "intro":"",
+      "avatar":"core/workflow/template/workflowStart",
+      "flowNodeType":"workflowStart",
+      "position":{
+        "x":558.4082376415505,
+        "y":123.72387429194112
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "reference",
+            "textarea"
+          ],
+          "valueType":"string",
+          "label":"workflow:user_question",
+          "toolDescription":"workflow:user_question",
+          "required":true
+        }
+      ],
+      "outputs":[
+        {
+          "id":"userChatInput",
+          "key":"userChatInput",
+          "label":"common:core.module.input.label.user question",
+          "type":"static",
+          "valueType":"string"
+        },
+        {
+          "id":"userFiles",
+          "key":"userFiles",
+          "label":"app:workflow.user_file_input",
+          "description":"app:workflow.user_file_input_desc",
+          "type":"static",
+          "valueType":"arrayString"
+        }
+      ]
+    },
+    {
+      "nodeId":"7BdojPlukIQw",
+      "name":"AI dialogue",
+      "intro":"AI Large Model Dialogue",
+      "avatar":"core/workflow/template/aiChat",
+      "flowNodeType":"chatNode",
+      "showStatus":true,
+      "position":{
+        "x":1106.3238387960757,
+        "y":-350.6030674683474
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"model",
+          "renderTypeList":[
+            "settingLLMModel",
+            "reference"
+          ],
+          "label":"",
+          "valueType":"string",
+          "value":"llama3:latest"
+        },
+        {
+          "key":"temperature",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "value":3,
+          "valueType":"number",
+          "min":0,
+          "max":10,
+          "step":1
+        },
+        {
+          "key":"maxToken",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "value":1950,
+          "valueType":"number",
+          "min":100,
+          "max":4000,
+          "step":50
+        },
+        {
+          "key":"isResponseAnswerText",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "value":true,
+          "valueType":"boolean"
+        },
+        {
+          "key":"aiChatQuoteRole",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string",
+          "value":"system"
+        },
+        {
+          "key":"quoteTemplate",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string"
+        },
+        {
+          "key":"quotePrompt",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string"
+        },
+        {
+          "key":"systemPrompt",
+          "renderTypeList":[
+            "textarea",
+            "reference"
+          ],
+          "max":3000,
+          "valueType":"string",
+          "label":"core.ai.Prompt",
+          "description":"core.app.tip.systemPromptTip",
+          "placeholder":"core.app.tip.chatNodeSystemPromptTip",
+          "value":"gfhgfh"
+        },
+        {
+          "key":"history",
+          "renderTypeList":[
+            "numberInput",
+            "reference"
+          ],
+          "valueType":"chatHistory",
+          "label":"core.module.input.label.chat history",
+          "required":true,
+          "min":0,
+          "max":30,
+          "value":6
+        },
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "reference",
+            "textarea"
+          ],
+          "valueType":"string",
+          "label":"common:core.module.input.label.user question",
+          "required":true,
+          "toolDescription":"common:core.module.input.label.user question",
+          "value":[
+            "workflowStartNodeId",
+            "userChatInput"
+          ]
+        },
+        {
+          "key":"quoteQA",
+          "renderTypeList":[
+            "settingDatasetQuotePrompt"
+          ],
+          "label":"",
+          "debugLabel":"common:core.module.Dataset quote.label",
+          "description":"",
+          "valueType":"datasetQuote",
+          "value":[
+            "iKBoX2vIzETU",
+            "quoteQA"
+          ]
+        },
+        {
+          "key":"aiChatVision",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"boolean",
+          "value":true
+        }
+      ],
+      "outputs":[
+        {
+          "id":"history",
+          "key":"history",
+          "required":true,
+          "label":"common:core.module.output.label.New context",
+          "description":"common:core.module.output.description.New context",
+          "valueType":"chatHistory",
+          "valueDesc":"{ obj: System | Human | AI; value: string; }[]",
+          "type":"static"
+        },
+        {
+          "id":"answerText",
+          "key":"answerText",
+          "required":true,
+          "label":"common:core.module.output.label.Ai response content",
+          "description":"common:core.module.output.description.Ai response content",
+          "valueType":"string",
+          "type":"static"
+        }
+      ]
+    },
+    {
+      "nodeId":"iKBoX2vIzETU",
+      "name":"Knowledge Base Search",
+      "intro":"Call the 'semantic retrieval' and 'full-text retrieval' capabilities to search for reference content that may be relevant to the problem from the 'knowledge base'",
+      "avatar":"core/workflow/template/datasetSearch",
+      "flowNodeType":"datasetSearchNode",
+      "showStatus":true,
+      "position":{
+        "x":918.5901682164496,
+        "y":-227.11542247619582
+      },
+      "version":"481",
+      "inputs":[
+        {
+          "key":"datasets",
+          "renderTypeList":[
+            "selectDataset",
+            "reference"
+          ],
+          "label":"core.module.input.label.Select dataset",
+          "value":[
+            {
+              "datasetId":"6746e7eeea059f95ac6179df"
+            }
+          ],
+          "valueType":"selectDataset",
+          "list":[
+
+          ],
+          "required":true
+        },
+        {
+          "key":"similarity",
+          "renderTypeList":[
+            "selectDatasetParamsModal"
+          ],
+          "label":"",
+          "value":0.4,
+          "valueType":"number"
+        },
+        {
+          "key":"limit",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "value":1500,
+          "valueType":"number"
+        },
+        {
+          "key":"searchMode",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string",
+          "value":"embedding"
+        },
+        {
+          "key":"usingReRank",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"boolean",
+          "value":false
+        },
+        {
+          "key":"datasetSearchUsingExtensionQuery",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"boolean",
+          "value":true
+        },
+        {
+          "key":"datasetSearchExtensionModel",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string"
+        },
+        {
+          "key":"datasetSearchExtensionBg",
+          "renderTypeList":[
+            "hidden"
+          ],
+          "label":"",
+          "valueType":"string",
+          "value":""
+        },
+        {
+          "key":"userChatInput",
+          "renderTypeList":[
+            "reference",
+            "textarea"
+          ],
+          "valueType":"string",
+          "label":"workflow:user_question",
+          "toolDescription":"workflow:content_to_search",
+          "required":true,
+          "value":[
+            "workflowStartNodeId",
+            "userChatInput"
+          ]
+        }
+      ],
+      "outputs":[
+        {
+          "id":"quoteQA",
+          "key":"quoteQA",
+          "label":"common:core.module.Dataset quote.label",
+          "description":"workflow:special_array_format",
+          "type":"static",
+          "valueType":"datasetQuote",
+          "valueDesc":"{ id: string; datasetId: string; collectionId: string; sourceName: string; sourceId?: string; q: string; a: string }[]"
+        }
+      ]
+    }
+  ],
+  "edges":[
+    {
+      "source":"workflowStartNodeId",
+      "target":"iKBoX2vIzETU",
+      "sourceHandle":"workflowStartNodeId-source-right",
+      "targetHandle":"iKBoX2vIzETU-target-left"
+    },
+    {
+      "source":"iKBoX2vIzETU",
+      "target":"7BdojPlukIQw",
+      "sourceHandle":"iKBoX2vIzETU-source-right",
+      "targetHandle":"7BdojPlukIQw-target-left"
+    }
+  ],
+  "chatConfig":{
+    "questionGuide":false,
+    "ttsConfig":{
+      "type":"web"
+    },
+    "whisperConfig":{
+      "open":false,
+      "autoSend":false,
+      "autoTTSResponse":false
+    },
+    "scheduledTriggerConfig":{
+      "cronString":"",
+      "timezone":"Asia/Shanghai",
+      "defaultPrompt":""
+    },
+    "chatInputGuide":{
+      "open":false,
+      "textList":[
+
+      ],
+      "customUrl":""
+    },
+    "instruction":"",
+    "variables":[
+
+    ],
+    "welcomeText":"Hello, I am Knowledge Base Assistant. Please don't forget to select the knowledge base. [Who are you] [How to use]"
+  },
+  "type":"simple",
+  "isPublish":true,
+  "versionName":"2024-12-03 09:39:01"
+}
\ No newline at end of file
index 58a98c0..b8a56e4 100644 (file)
@@ -42,10 +42,5 @@ create table if not exists application(
     temperature float,
     top_p float,
     opening_remarks varchar(255)
-);
-
-create table if not exists cookie(
-    maas_platform_name varchar(255) primary key,
-    cookie text
 )
 
diff --git a/llm-adaptation/src/main/resources/mapper/FastGptApplicationMapper.xml b/llm-adaptation/src/main/resources/mapper/FastGptApplicationMapper.xml
new file mode 100644 (file)
index 0000000..31ed447
--- /dev/null
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.onap.usecaseui.llmadaptation.mapper.FastGptApplicationMapper">
+    <insert id="insertApplication">
+        insert into application(application_id,
+                                application_name,
+                                application_description,
+                                application_type,
+                                knowledge_base_id,
+                                model_id,
+                                model_name,
+                                prompt,
+                                temperature,
+                                top_p,
+                                opening_remarks
+                                )
+        values (#{application.applicationId},
+                #{application.applicationName},
+                #{application.applicationDescription},
+                #{application.applicationType},
+                #{application.knowledgeBaseId},
+                #{application.largeModelId},
+                #{application.largeModelName},
+                #{application.prompt},
+                #{application.temperature},
+                #{application.top_p},
+                #{application.openingRemarks})
+    </insert>
+    <delete id="deleteApplicationById">
+        delete from application where application_id = #{applicationId}
+    </delete>
+
+
+    <select id="getAllApplication" resultType="org.onap.usecaseui.llmadaptation.bean.Application">
+        select application_id as applicationId,
+               application_name as applicationName,
+               application_description as applicationDescription,
+               application_type as applicationType,
+               knowledge_base_id as knowledgeBaseId,
+               model_id as largeModelId,
+               model_name as largeModelName,
+               prompt as prompt,
+               temperature as temperature,
+               top_p as top_p,
+               opening_remarks as openingRemarks
+        from application
+
+
+    </select>
+    <select id="getApplicationById" resultType="org.onap.usecaseui.llmadaptation.bean.Application">
+        select application_id as applicationId,
+               application_name as applicationName,
+               application_description as applicationDescription,
+               application_type as applicationType,
+               knowledge_base_id as knowledgeBaseId,
+               model_id as largeModelId,
+               model_name as largeModelName,
+               prompt as prompt,
+               temperature as temperature,
+               top_p as top_p,
+               opening_remarks as openingRemarks
+        from application where application_id = #{applicationId}
+    </select>
+</mapper>
\ No newline at end of file
diff --git a/llm-adaptation/src/main/resources/mapper/FastGptDatasetMapper.xml b/llm-adaptation/src/main/resources/mapper/FastGptDatasetMapper.xml
new file mode 100644 (file)
index 0000000..836ced9
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.onap.usecaseui.llmadaptation.mapper.FastGptDatasetMapper">
+    <insert id="insertKnowledgeBaseRecord">
+        insert into knowledge_base(knowledge_base_id,
+                                   knowledge_base_name,
+                                   knowledge_base_description,
+                                   operator_id,
+                                   operator_name,
+                                   maas_platform_id,
+                                   maas_platform_name,
+                                   update_time)
+        values (#{knowledgeBase.knowledgeBaseId},
+                #{knowledgeBase.knowledgeBaseName},
+                #{knowledgeBase.knowledgeBaseDescription},
+                #{knowledgeBase.operatorId},
+                #{knowledgeBase.operatorName},
+                #{knowledgeBase.maaSPlatformId},
+                #{knowledgeBase.maaSPlatformName},
+                to_timestamp(#{knowledgeBase.updateTime},'yyyy-MM-dd HH24:mi:ss'))
+    </insert>
+    <insert id="insertFileName">
+        insert into file(file_id,file_name,knowledge_base_id)
+        values (#{fileId},#{fileName},#{knowledgeBaseId})
+    </insert>
+    <select id="getKnowledgeBaseRecords" resultType="org.onap.usecaseui.llmadaptation.bean.KnowledgeBase">
+        select knowledge_base_id as knowledgeBaseId,
+               knowledge_base_name as knowledgeBaseName,
+               knowledge_base_description as knowledgeBaseDescription,
+               operator_id as operatorId,
+               operator_name as operatorName,
+               maas_platform_id as maaSPlatformId,
+               maas_platform_name as maaSPlatformName,
+               to_char(update_time,'yyyy-mm-dd HH24:mi:ss') as updateTime
+        from knowledge_base
+    </select>
+    <select id="getFileNamesByKnowledgeBaseId" resultType="java.lang.String">
+        select file_name from file where knowledge_base_id = #{knowledgeBaseId}
+    </select>
+    <select id="getKnowledgeBaseRecordById" resultType="org.onap.usecaseui.llmadaptation.bean.KnowledgeBase">
+        select knowledge_base_id as knowledgeBaseId,
+               knowledge_base_name as knowledgeBaseName,
+               knowledge_base_description as knowledgeBaseDescription,
+               operator_id as operatorId,
+               operator_name as operatorName,
+               maas_platform_id as maaSPlatformId,
+               maas_platform_name as maaSPlatformName,
+               to_char(update_time,'yyyy-mm-dd HH24:mi:ss') as updateTime
+        from knowledge_base
+        where  knowledge_base_id = #{knowledgeBaseId}
+    </select>
+    <select id="getKnowledgeBaseByMaaSId" resultType="org.onap.usecaseui.llmadaptation.bean.KnowledgeBase">
+        select knowledge_base_id as knowledgeBaseId,
+               knowledge_base_name as knowledgeBaseName
+        from knowledge_base
+        where  maas_platform_id = #{maaSPlatformId}
+    </select>
+
+    <delete id="deleteKnowledgeBaseByUuid">
+        delete from knowledge_base where knowledge_base_id = #{knowledgeBaseId}
+    </delete>
+    <delete id="deleteFileById">
+        delete from file where knowledge_base_id = #{knowledgeBaseId}
+    </delete>
+
+</mapper>
\ No newline at end of file