Skip to content

Commit

Permalink
[feature] : support kimi Ai (#2171)
Browse files Browse the repository at this point in the history
Co-authored-by: Logic <[email protected]>
Co-authored-by: tomsun28 <[email protected]>
  • Loading branch information
3 people authored Jul 3, 2024
1 parent 1cb293a commit b4d0e77
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,12 @@ public enum AiTypeEnum {
/**
* alibabaAi
*/
alibabaAi;
alibabaAi,

/**
* Moonshot AI
*/
kimiAi;


/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public ResponseEntity<Message<Void>> deleteMonitors(
@Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
monitorService.cancelManageMonitors(new HashSet<>(ids));
monitorService.deleteMonitors(new HashSet<>(ids));
}
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
Expand All @@ -173,7 +173,7 @@ public ResponseEntity<Message<Void>> cancelManageMonitors(
@Parameter(description = "Monitoring ID List", example = "6565463543") @RequestParam(required = false) List<Long> ids
) {
if (ids != null && !ids.isEmpty()) {
monitorService.deleteMonitors(new HashSet<>(ids));
monitorService.cancelManageMonitors(new HashSet<>(ids));
}
Message<Void> message = Message.success();
return ResponseEntity.ok(message);
Expand Down
Original file line number Diff line number Diff line change
@@ -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<AiMessage> 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;


}



Original file line number Diff line number Diff line change
@@ -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<Choice> 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;
}

}

Original file line number Diff line number Diff line change
@@ -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<String> 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");
}
}
6 changes: 3 additions & 3 deletions manager/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:

0 comments on commit b4d0e77

Please sign in to comment.