From b4d0e77c994abeca8ffca7b07192434ee1acf31d Mon Sep 17 00:00:00 2001 From: linDong <56677297@qq.com> Date: Thu, 4 Jul 2024 07:52:48 +0800 Subject: [PATCH] [feature] : support kimi Ai (#2171) Co-authored-by: Logic Co-authored-by: tomsun28 --- .../common/constants/AiConstants.java | 31 +++++ .../common/constants/AiTypeEnum.java | 7 +- .../controller/MonitorsController.java | 4 +- .../pojo/dto/KimiAiRequestParamDTO.java | 70 +++++++++++ .../manager/pojo/dto/KimiAiResponse.java | 93 +++++++++++++++ .../manager/service/KimiAiServiceImpl.java | 112 ++++++++++++++++++ manager/src/main/resources/application.yml | 6 +- 7 files changed, 317 insertions(+), 6 deletions(-) create mode 100644 manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiRequestParamDTO.java create mode 100644 manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiResponse.java create mode 100644 manager/src/main/java/org/apache/hertzbeat/manager/service/KimiAiServiceImpl.java diff --git a/common/src/main/java/org/apache/hertzbeat/common/constants/AiConstants.java b/common/src/main/java/org/apache/hertzbeat/common/constants/AiConstants.java index 621085b063e..bf8f0893009 100644 --- a/common/src/main/java/org/apache/hertzbeat/common/constants/AiConstants.java +++ b/common/src/main/java/org/apache/hertzbeat/common/constants/AiConstants.java @@ -81,5 +81,36 @@ interface AliAiConstants { float TEMPERATURE = 0.9f; + } + + /** + * Kimi Ai constants + */ + interface KimiAiConstants { + + /** + * Kimi Ai URL + */ + String URL = "https://api.moonshot.cn/v1/chat/completions"; + + /** + * request role param + */ + String REQUEST_ROLE = "user"; + + /** + * The model outputs the maximum tokens, with a maximum output of 8192 and a default value of 1024 + */ + Integer MAX_TOKENS = 1024; + + /** + * The sampling temperature, which controls the randomness of the output, must be positive + * The value ranges from 0.0 to 1.0, and cannot be equal to 0. The default value is 0.95. The larger the value, + * the more random and creative the output will be. The smaller the value, the more stable or certain the output will be + * You are advised to adjust top_p or temperature parameters based on application scenarios, but do not adjust the two parameters at the same time + */ + float TEMPERATURE = 0.9f; + + } } diff --git a/common/src/main/java/org/apache/hertzbeat/common/constants/AiTypeEnum.java b/common/src/main/java/org/apache/hertzbeat/common/constants/AiTypeEnum.java index 87d7fc4d813..6225b229756 100644 --- a/common/src/main/java/org/apache/hertzbeat/common/constants/AiTypeEnum.java +++ b/common/src/main/java/org/apache/hertzbeat/common/constants/AiTypeEnum.java @@ -30,7 +30,12 @@ public enum AiTypeEnum { /** * alibabaAi */ - alibabaAi; + alibabaAi, + + /** + * Moonshot AI + */ + kimiAi; /** diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java b/manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java index 9ab7eac9719..46e1129b3d7 100644 --- a/manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java +++ b/manager/src/main/java/org/apache/hertzbeat/manager/controller/MonitorsController.java @@ -160,7 +160,7 @@ public ResponseEntity> deleteMonitors( @Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List ids ) { if (ids != null && !ids.isEmpty()) { - monitorService.cancelManageMonitors(new HashSet<>(ids)); + monitorService.deleteMonitors(new HashSet<>(ids)); } Message message = Message.success(); return ResponseEntity.ok(message); @@ -173,7 +173,7 @@ public ResponseEntity> cancelManageMonitors( @Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List ids ) { if (ids != null && !ids.isEmpty()) { - monitorService.deleteMonitors(new HashSet<>(ids)); + monitorService.cancelManageMonitors(new HashSet<>(ids)); } Message message = Message.success(); return ResponseEntity.ok(message); diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiRequestParamDTO.java b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiRequestParamDTO.java new file mode 100644 index 00000000000..29153ad4579 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiRequestParamDTO.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.pojo.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * zhiPu Request param + */ + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class KimiAiRequestParamDTO { + + /** + * ai version + */ + private String model; + + /** + * request message + */ + private List messages; + + /** + * The sampling temperature, which controls the randomness of the output, must be positive + * The value ranges from 0.0 to 1.0, and cannot be equal to 0. The default value is 0.95. + * The larger the value, the more random and creative the output will be. The smaller the value, the more stable or certain the output will be + * You are advised to adjust top_p or temperature parameters based on application scenarios, but do not adjust the two parameters at the same time + */ + private float temperature; + + /** + * The model outputs the maximum tokens, with a maximum output of 8192 and a default value of 1024 + */ + @JsonProperty("max_tokens") + private Integer maxTokens; + + /** + * stream response + */ + private Boolean stream = Boolean.FALSE; + + +} + + + diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiResponse.java b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiResponse.java new file mode 100644 index 00000000000..58458565d64 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/pojo/dto/KimiAiResponse.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.pojo.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * ZhiPuAiResponse + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class KimiAiResponse { + + /** + * Task order number generated by the AI open platform. Use this order number when invoking the request result interface + */ + private String id; + + /** + * The request creation time is a Unix timestamp in seconds + */ + private Long created; + + /** + * response message + */ + private List choices; + + /** + * Returns the number of tokens invoked by the model at the end. + */ + private Tokens usage; + + /** + * Choice + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public class Choice { + private int index; + private AiMessage delta; + } + + /** + * Tokens + */ + @Data + @AllArgsConstructor + @NoArgsConstructor + public class Tokens { + + /** + * The number of tokens entered by users + */ + @JsonProperty("prompt_tokens") + private Integer promptTokens; + + /** + * The number of tokens that the model outputs + */ + @JsonProperty("completion_tokens") + private Integer completionTokens; + + /** + * Total number of tokens + */ + @JsonProperty("total_tokens") + private Integer totalTokens; + } + +} + diff --git a/manager/src/main/java/org/apache/hertzbeat/manager/service/KimiAiServiceImpl.java b/manager/src/main/java/org/apache/hertzbeat/manager/service/KimiAiServiceImpl.java new file mode 100644 index 00000000000..31820487230 --- /dev/null +++ b/manager/src/main/java/org/apache/hertzbeat/manager/service/KimiAiServiceImpl.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.hertzbeat.manager.service; + +import com.alibaba.fastjson.JSON; +import java.util.List; +import java.util.Objects; +import javax.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.apache.hertzbeat.common.constants.AiConstants; +import org.apache.hertzbeat.common.constants.AiTypeEnum; +import org.apache.hertzbeat.manager.pojo.dto.AiMessage; +import org.apache.hertzbeat.manager.pojo.dto.KimiAiRequestParamDTO; +import org.apache.hertzbeat.manager.pojo.dto.KimiAiResponse; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; +import org.springframework.web.reactive.function.BodyInserters; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; + +/** + * Kimi Ai + */ +@Service("KimiAiServiceImpl") +@Slf4j +public class KimiAiServiceImpl implements AiService { + + @Value("${aiConfig.model:moonshot-v1-8k}") + private String model; + + @Value("${aiConfig.api-key}") + private String apiKey; + + private WebClient webClient; + + @PostConstruct + private void init() { + this.webClient = WebClient.builder() + .baseUrl(AiConstants.KimiAiConstants.URL) + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .defaultHeader(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey) + .exchangeStrategies(ExchangeStrategies.builder() + .codecs(item -> item.defaultCodecs().maxInMemorySize(16 * 1024 * 1024)) + .build()) + .build(); + } + + @Override + public AiTypeEnum getType() { + return AiTypeEnum.kimiAi; + } + + @Override + public Flux requestAi(String text) { + + checkParam(text, apiKey); + KimiAiRequestParamDTO zhiPuRequestParamDTO = KimiAiRequestParamDTO.builder() + .model(model) + .stream(Boolean.TRUE) + .maxTokens(AiConstants.KimiAiConstants.MAX_TOKENS) + .temperature(AiConstants.KimiAiConstants.TEMPERATURE) + .messages(List.of(new AiMessage(AiConstants.KimiAiConstants.REQUEST_ROLE, text))) + .build(); + + + return webClient.post() + .body(BodyInserters.fromValue(zhiPuRequestParamDTO)) + .retrieve() + .bodyToFlux(String.class) + .filter(aiResponse -> !"[DONE]".equals(aiResponse)) + .map(this::convertToResponse) + .doOnError(error -> log.info("AiResponse Exception:{}", error.toString())); + + } + + private String convertToResponse(String aiRes) { + try { + KimiAiResponse kimiAiResponse = JSON.parseObject(aiRes, KimiAiResponse.class); + if (Objects.nonNull(kimiAiResponse)) { + KimiAiResponse.Choice choice = kimiAiResponse.getChoices().get(0); + return choice.getDelta().getContent(); + } + } catch (Exception e) { + log.info("convertToResponse Exception:{}", e.toString()); + } + return ""; + } + + private void checkParam(String param, String apiKey) { + Assert.notNull(param, "text is null"); + Assert.notNull(apiKey, "aiConfig.api-key is null"); + } +} diff --git a/manager/src/main/resources/application.yml b/manager/src/main/resources/application.yml index c1089081d78..90d6e43e703 100644 --- a/manager/src/main/resources/application.yml +++ b/manager/src/main/resources/application.yml @@ -203,9 +203,9 @@ scheduler: # AI config # See the documentation for details : https://hertzbeat.apache.org/zh-cn/docs/help/aiConfig aiConfig: - # AI Type:zhiPu、alibabaAi + # AI Type:zhiPu、alibabaAi、kimiAi type: - # Model name:glm-4、qwen-turbo - model: + # Model name:glm-4、qwen-turbo、moonshot-v1-8k + model: glm-4 # api key api-key: \ No newline at end of file